设计模式-Java-单例模式

    技术2023-11-07  89

    一、应用场景

    一般会在以下两种情况下采用单例模式:

    资源共享的情况下,避免由于资源操作时导致的性能或损耗等。控制资源的情况下,方便资源之间的互相通信。

    场景举例:

    为了方便线程池对池中的线程进行管理,一般线程池也会采用单例模式。 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件 Windows的Task Manager(任务管理器)就是很典型的单例模式。Windows的Recycle Bin(回收站)也是典型的单例应用。 网站的计数器,一般也是采用单例模式实现,否则难以同步。  Web应用的配置对象的读取,由于配置文件是共享的资源。应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

    二、单例原则

    构造方法私有化。以静态方法或者枚举返回实例。实例化变量引用私有化。确保反序列转换时不会重新构建对象。

    三、怎么写单例模式

    (一)饿汉模式

    饿汉模式在类被初始化时就已经在内存中创建了对象,以空间换时间,因此不存在线程安全问题。

    package com.fuping.liuqu.demo.design.pattern.singleton; /** * 单例模式,饿汉模式 */ public class Singleton1 { private String field; public String getField() { return field; } public void setField(String field) { this.field = field; } private static final Singleton1 INSTANCE = new Singleton1(); private Singleton1() { } public static Singleton1 getInstance() { return INSTANCE; } }

    (二)懒汉模式

    懒汉模式在方法被调用后才创建对象,以时间换空间,在多线程环境下存在风险。

    package com.fuping.liuqu.demo.design.pattern.singleton; /** * 单例模式,懒汉模式 */ public class Singleton2 { private String field; private static Singleton2 instance = null; public String getField() { return field; } public void setField(String field) { this.field = field; } private Singleton2() { } public static Singleton2 getInstance() { if (null == instance) { instance = new Singleton2(); } return instance; } }

    (三)双重检入模式

    必须给INSTANCE增加volatile描述,以解决指令重排序的问题。 

    package com.fuping.liuqu.demo.design.pattern.singleton; /** * 单例模式,双重检入模式 */ public class Singleton3 { private String field; private volatile static Singleton3 INSTANCE = null; public String getField() { return field; } public void setField(String field) { this.field = field; } private Singleton3() { } public static Singleton3 getInstance() { if (null == INSTANCE) { synchronized (Singleton3.class) { if (null == INSTANCE) { synchronized (Singleton3.class) { INSTANCE = new Singleton3(); } } } } return INSTANCE; } }

    (四)静态内部类模式

    静态内部类的优势在于第一次加载Singleton4类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加载SingletonHolder类并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton4 类的唯一性。

    package com.fuping.liuqu.demo.design.pattern.singleton; /** * 单例模式,静态内部类模式 */ public class Singleton4 { private Singleton4() { } public Singleton4 getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final Singleton4 INSTANCE = new Singleton4(); } }

    (五)单元素枚举模式

    优势:

    可以避免反射攻击问题(构造方法私有化,并不能阻止类被反射)可以解决序列化问题 package com.fuping.liuqu.demo.design.pattern.singleton; /** * 单例模式,枚举类模式 */ public enum Singleton5 { INSTANCE; private String field; public String getField() { return field; } public void setField(String field) { this.field = field; } public Singleton5 getInstance() { return INSTANCE; } }

     

    Processed: 0.014, SQL: 9