单例模式

1.定义:单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,一个类只有一个对象实例。

2.结构:

  

3.实现

1)饿汉模式:不管有没有使用,对象都已经创建了;

 1 // 饿汉式单例
 2 public class Singleton {
 3     // 私有构造
 4     private Singleton() {}
 5     // 饿汉模式对象从开始就已经创建了
 6     private static Singleton single = new Singleton();
 7     // 静态工厂方法
 8     public static Singleton getInstance() {
 9         return single;
10     }
11 }

  饿汉式单例在类加载初始化就创建好了一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效)

2)懒汉模式:如果未调用,对象不会创建,只有被使用时,创建对象。

 1 // 懒汉式单例(不考虑多线程情况)
 2 public class Singleton {
 3     // 懒汉模式对象在使用时才进行创建
 4     private static Singleton instance ; // 将构造器私有化
 5     private Singleton() {}
 6     // 提供公开的方法获取当前类的对象
 7     public static Singleton getInstance() {
 8         // 判断对象是否存在,如果不存在new
 9         if(instance==null) {
10            instance = new Singleton();
11         }
12         return instance; 
13     } 
14 }

  该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个single对象。

3)使用双重校验锁实现

 1 // 有同步锁效果的懒汉模式
 2 public class Singleton {
 3     private static volatile Singleton instance = null;
 4     private Singleton() {}
 5     public static Singleton getInstance() {
 6         // 双重检查
 7         if (instance == null) {
 8             // 相当于对getInstance()进行了同步锁
 9             synchronized (Singleton.class) {
10                 if (instance == null) {
11                     instance = new SingletonB();
12                 }
13             }
14         }
15         return instance; 
16     }
17 }

  在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式解决了多个实例对象问题,使用双重检查进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

4.特点

  i. 单例类只能有一个实例;

  ii.单例类必须自己创建自己的唯一实例;

  iii.单例类必须给所有其他对象提供这一实例;

5.优缺点

  优点:

    1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

    2)避免对资源的多重占用(比如写文件操作)。

  缺点:

    没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

6.适用环境

  i.一个全局使用的类频繁地创建或销毁

  ii.要求生产唯一序列号

  iii.web中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来

  iv.创建的一个对象需要消耗的资源过多,比如IO与数据库的连接等

  v.在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以由若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。

7.应用

  通过单例模式实现唯一序列号效果,有一个类Singleton,有一个静态属性i,这个属性从1开始,当调用sequence()方法时,自增1。模拟一个多线程效果,有10个线程调用Singleton类的sequence()方法,每个线程调用时,输出当前序列号。

posted @ 2019-11-25 12:26  MrHH  阅读(355)  评论(0编辑  收藏  举报