一、单例模式1、什么是单例模式采取一定的方法,使程序中的某个类只存在一个实例对象,且该类对外提供一个获取该对象的方法(一般为静态方法)。 2、单例模式分类(1)饿汉式(2种写法,线程安全) (2)懒汉式(3种写法) (3)双重检查(推荐使用) 3、饿汉式单例模式(静态常量版)(1)步骤: package singleton.pattern.demo1; /** * 演示 饿汉式单例模式,静态变量版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 饿汉式单例模式,静态变量版 */ class Singleton { // 在类的内部创建实例对象。使用静态变量,只被加载一次。 private static Singleton singleton = new Singleton(); /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { return singleton; } } (3)优缺点: (4)UML图:
4、饿汉式单例模式(静态代码块)(1)步骤: package singleton.pattern.demo2; /** * 演示 饿汉式单例模式,静态代码块版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 饿汉式单例模式,静态代码块版 */ class Singleton { // 在类的内部声明一个实例对象 private static Singleton singleton; static { // 在代码块中实例化一个对象,同样只加载一次 singleton = new Singleton(); } /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { return singleton; } } (3)优缺点同上例 饿汉式单例模式(静态常量版) 5、懒汉式单例模式(线程不安全)(1)步骤: package singleton.pattern.demo3; /** * 演示 懒汉式单例模式,线程不安全版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 懒汉式单例模式,线程不安全版 */ class Singleton { // 在类的内部声明一个实例对象 private static Singleton singleton; /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象。 当调用该方法时,才去检查并创建一个实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { if (singleton == null) { singleton = new Singleton(); } return singleton; } } (3)优缺点: 6、懒汉式单例模式(线程安全,同步方法)(1)步骤: package singleton.pattern.demo4; /** * 演示 懒汉式单例模式,线程安全,同步方法版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 懒汉式单例模式,线程安全,同步方法版 */ class Singleton { // 在类的内部声明一个实例对象 private static Singleton singleton; /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象,并给方法加个synchronized关键字,解决同步的问题。 * 当调用该方法时,才去检查并创建一个实例对象。 * * @return 实例对象 */ public static synchronized Singleton getSingleTon() { if (singleton == null) { singleton = new Singleton(); } return singleton; } } (3)优缺点:
7、懒汉式单例模式(同步代码块方法,线程不一定安全)(1)步骤: package singleton.pattern.demo5; /** * 演示 懒汉式单例模式,线程不一定安全,同步代码块版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 懒汉式单例模式,线程不一定安全,同步代码块版 */ class Singleton { // 在类的内部声明一个实例对象 private static Singleton singleton; /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象,在方法内部加个同步代码块。 当调用该方法时,才去检查并创建一个实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } } (3)优缺点:
8、双重检查(Double Check)(1)步骤: package singleton.pattern.demo6; /** * 演示 单例模式,双重检查版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 单例模式,双重检查版 */ class Singleton { // 在类的内部声明一个实例对象 private static volatile Singleton singleton; /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 向外暴露一个静态的公共方法用于获取实例对象,在方法内部加个同步代码块,在代码块内部增加一个检查处理。 当调用该方法时,才去检查并创建一个实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } } (3)优缺点:
9、静态内部类(1)步骤: package singleton.pattern.demo7; /** * 演示 单例模式,静态内部类版 * */ public class Demo { public static void main(String[] args) { Singleton singleton1 = Singleton.getSingleTon(); Singleton singleton2 = Singleton.getSingleTon(); System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 单例模式,静态内部类版 */ class Singleton { /** * 构造器私有化(防止通过new创建实例对象) */ private Singleton() { } /** * 静态内部类,在被调用的时候才会被加载,实现懒加载。 且内部使用静态常量实例化一个对象,保证了线程安全问题。 */ public static class SingleTonInstance { public static final Singleton INSTANCE = new Singleton(); } /** * 向外暴露一个静态的公共方法用于获取实例对象,在方法内部加个同步代码块,在代码块内部增加一个检查处理。 当调用该方法时,才去检查并创建一个实例对象。 * * @return 实例对象 */ public static Singleton getSingleTon() { return SingleTonInstance.INSTANCE; // 调用静态内部类的静态属性 } } (3)优缺点: (4)UML图:
10、枚举(1)步骤: package singleton.pattern; /** * 演示 单例模式,枚举版 * */ public class Demo { public static void main(String[] args) { SingleTon singleton1 = SingleTon.INSTACNE; SingleTon singleton2 = SingleTon.INSTACNE; System.out.println(singleton1 == singleton2); // 由于获取的为同一个对象,所以输出为true } } /** * 单例模式,枚举版 */ enum SingleTon { INSTACNE; public void show() { System.out.println("hello world"); } } (3)优缺点:
11、JDK中的单例模式举例(Runtime)(1)部分源码 public class Runtime { private static Runtime currentRuntime = new Runtime(); /** * Returns the runtime object associated with the current Java application. * Most of the methods of class <code>Runtime</code> are instance * methods and must be invoked with respect to the current runtime object. * * @return the <code>Runtime</code> object associated with the current * Java application. */ public static Runtime getRuntime() { return currentRuntime; } /** Don't let anyone else instantiate this class */ private Runtime() {} } (2)可以看到上述代码中采用的是 饿汉式单例模式(静态变量版)。 12、单例模式使用注意(1)当频繁创建、销毁某个对象时,可以采用单例模式。
|
|