对码当歌,猿生几何?

设计模式之单例模式

1.定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2.动机

对于一些类来说,只有一个实例是很重要的。最好的方法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。这就是Singleton模式。

3.适用性

当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需要更改代码就能使用一个扩展的实例时。

4.类图

1.jpg

5.要素

1.私有的构造方法
2.指向自己实例的私有静态方法
3.以自己实例为返回值的静态的共有的方法

6.优点

1.在内存中只有一个对象,节省内存空间
2.避免频繁的创建销毁对象,可以提高性能
3.避免对共享资源的多重占用
4.可以全局访问

7.单线程环境下的实现

饿汉式单例

public class Singleton {private static Singleton singleton = new Singleton();private Singleton(){}public static Singleton getInstance(){return singleton;

    }

}

懒汉式单例

public class Singleton {private static Singleton singleton;private Singleton(){}public static synchronized Singleton getInstance(){if(singleton==null){

            singleton = new Singleton();

        }return singleton;

    }

}

8.多线程下的单例模式

通过增加synchronized关键字到getInstance()方法中,迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法,也就是说,不会有两个线程可以同时进入这个方法

public class Singleton {private static Singleton singleton;private Singleton() {}public static synchronized Singleton getInstance() {if(singleton == null) {
            singleton = new Singleton();
        }return singleton;
    }
}

这个可以解决多线程问题,但随之而来的是同步会降低性能!!!!!!!
而且只有第一次执行此方法时,才真正需要同步,一旦设置好变量,就不需要同步这个方法了。
使用“双重检查加锁”,在getInstance()中减少使用同步

public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance() {if(singleton == null) {
            synchronized (Singleton.class) {if(singleton == null) {
                    singleton = new Singleton();
                }
            }
        }return singleton;
    }
}

9.要点

  1. 单例模式确保程序中一个类最多只有一个实例

  2. 单例模式也提供访问这个实例的全局点

  3. 在java中实现单例模式需要私有的构造器,一个静态方法和一个静态变量。

  4. 确定在性能和资源上的限制,然后小心地选择适当的方案来实现单例,以解决多线程的问题

  5. 如果不是采用第五版的Java2,多重检查加锁实现会失效

  6. 如果使用多个类加载器,可能导致单例失效而产生多个实例

  7. 如果使用JVM1.2或之前的版本,必须建立单例注册表,以避免垃圾收集器将单例回收。

阅读更多