浅谈设计模式
2017-04-25 21:21
337 查看
存在目的
节约资源确保系统中某个类只有一个实例。(确保对象的唯一性,避免不必要的系统开销)单例模式的三个要点
由三个要点可知单例模式的结构特点:
内部实现只生成一个实例
提供静态的 getInstance() 工厂方法,让客户可以访问它的唯一实例
构造函数设为私有,在单例类内部定义一个静态 Singleton 类型对象,作为外界使用的唯一实例
基本 UML 图:
单例模式实现方式
饿汉式
public class EagerSingleton { private final static EagerSingleton instance = new EagerSingleton(); private EagerSingleton() { } public static EagerSingleton getInstance() { return instance; } }
类加载时静态变量 instance 会被初始化,此时私有构造方法被调用,单例唯一实例被创建,可确保实例的唯一性,但是类加载时需要创建实例,可能会导致加载时间变长。
懒汉式
public class LazySingleton { private static LazySingleton instance = null; private LazySingleton() { } public static LazySingleton getInstance() { if (instance == null) instance = new LazySingleton(); return instance; } }
这是最简单的懒汉式,只有用到的时候才去判断有没有实例,但是这样 getInstance() 并不能在多线程时保证只创建出一个实例,可以修改为:
public static LazySingleton getInstance() { if (instance == null) synchronized (LazySingleton.class) { instance = new LazySingleton(); } return instance; }
因为 判空和 new 对象的操作并不是原子操作,所以依然不能保证原自性,也就也可能,A、B 线程先后访问 instance 为 null,A 在 new 对象,而 B 在等锁,然后 B 又去 new 了一个实例。同样不能保证原子性。
把整个 getInstance() 方法加锁来保证原子性的话,作为一个单例被各种其他类访问的第一步都是在 getInstance(),这样会在多线程的时候影响执行效率,所以又有了下面这种:
public class LazySingleton { private static volatile LazySingleton instance = null; private LazySingleton() { } public static LazySingleton getInstance() { if (instance == null) synchronized (LazySingleton.class) { if (instance == null) instance = new LazySingleton(); } return instance; } }
这样貌似就完美的解决了执行效率和实例唯一性的问题。但是需要注意到的一点是:必须在 instance 前面加修饰符 volatile 来确保多线程正确处理。
volatile 只有在 JDK 1.5 以及以上的版本才能正确执行。volatile 会屏蔽一些 Java 虚拟机的优化,而影响执行效率。可见上面这种双重判断锁定也不是一种完美的单例解决方案。
静态内部类实现单例(完美方案)
public class Singleton { private Singleton() { } public static Singleton getInstance() { return HolderClass.instance; } private static class HolderClass{ private final static Singleton instance = new Singleton(); } }
这种方式实现了延时加载,保证了线程的安全性,又不影响系统性能。
单例模式优缺点
优点
单例模式提供了对唯一实例的受控访问,可以严格控制客户端怎样以及何时访问它由于系统内只存在一个对象,比较节约系统资源。对于创建开销比较大,或者频繁创建开销的使用单例可以明显的提升性能。
缺点
单例模式没有抽象层,不利于拓展违反了单一职责的原则,单例类既充当工厂,又充当产品的角色。将产品的创建和产品本身的功能融合到了一起。
长时间不被利用时,可能被当作垃圾回收掉。下次还要初始化实例。可能会引起必要的实例状态的丢失。
单例模式适用场景
系统只需要一个实例,或者是创建的开销太大,只允许创建一个实例客户端使用实例只允许通过一个公共访问点,除了公共访问点以外不允许其他的途径来访问实例。
PS:
单例模式也可以根据需要进行改造,改造成两例,三例等。相关文章推荐
- 设计模式浅谈
- 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- J2EE设计模式浅谈(一)
- Java设计模式浅谈
- 浅谈设计模式
- 浅谈设计模式(Bridge pattern和 Strategy pattern)
- 设计模式:浅谈行为模式State(C/C++ C#)
- 设计模式之策略模式浅谈
- 设计模式浅谈
- 浅谈设计模式(职责链与命令模式)
- 从设计模式Observer的实现看OOD的设计——浅谈“多态”的设计原则
- [转]浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- 浅谈BREW对面向对象,Windows,Java,设计模式的借鉴
- 浅谈设计模式(二)
- 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- 浅谈Route组件的设计思考与模式
- 设计模式之UML类图关系浅谈。
- 浅谈设计模式在JAVA中的具体运用
- 设计模式之策略模式浅谈