设计模式之单例模式

单例模式的定义:一个类只有一个实例,且该类能自行创建这个实例。(例子:电脑系统的任务管理器、回收站等)

单例模式的特点:

1.实现单例模式的类只有一个实例对象

2.该实例对象由单例类自己生成

3.单例类对外提供一个访问该单例的全局访问点

实现方式(一):真.懒汉模式

 1  public class SingleTon {
 2      // 1.自己创建对象,自给自足
 3      private static  SingleTon singleTon;
 4      // 2.加上private让外部的其他类无法通过new创建对象,不给别人new
 5      private SingleTon(){} 
 6      // 3.提供一个公共方法给外部,还是要给别人用
 7      public static  SingleTon getInstance(){
 8          // 这个判断是为了在单例对象不存在时才创建对象
 9          if( singleTon == null){
10              singleTon = new SingleTon();
11          }
12         return singleTon;
13      }
14  }

懒汉模式顾名思义就是需要使用的时候发现没有才去创建,而这种方式并没有考虑线程安全的问题。如果存在多个线程同时来调用getInstance方法就会生成多个实例对象,所有真的很懒,最好别这样。

优点:需要的时候才创建,减少了内存的初始压力                                     缺点:遇见多线程的情况相当于没用

实现方式(二):普通.懒汉模式

 1  public class SingleTon {
 2      // 1.自己创建对象,自给自足
 3      private static volatile SingleTon singleTon;
 4      // 2.加上private让外部的其他类无法通过new创建对象,不给别人new
 5      private SingleTon(){} 
 6      // 3.提供一个公共方法给外部,还是要给别人用
 7      public static synchronized SingleTon getInstance(){
 8          // 这个判断是为了多个线程调用时保证对象的唯一性
 9          if( singleTon == null){
10              singleTon = new SingleTon();
11          }
12          return singleTon;
13      }
14  }

懒汉模式常用的是这种类型的。通过关键字volatile和synchronized保证了在多线程的情况下生成对象时要进行同步使得单例类只有一个对象,不会掉链子,能够实现单例模式。

优点:同真.懒汉模式(这个倒是一脉相承)且线程安全                                               缺点:两个关键字保证了每次访问都需要同步,所以在性能上和资源消耗上要大一点

实现方式(三):饿汉模式

 1 public class SingleTon {
 2     // 1.自己创建对象
 3     private static volatile SingleTon singleTon = new SingleTon();
 4     // 2.加上private让外部的其他类无法通过new创建对象,不给别人new
 5     private SingleTon(){} 
 6     // 3.提供一个公共方法给外部,还是要给别人用
 7     public static synchronized SingleTon getInstance(){
 8         return singleTon;
 9     }
10 }

饿汉模式理解就是饿,有吃的跑的快,所以一上来就生成了实例对象,先捞到手再说,需要的时候直接用就行。

优点:因为是类一加载就创建了唯一实例对象,所以想通过多线程搞事情就没机会了                         缺点:一开始就加载到内存中,如果用的时候很晚会存在资源浪费

实现方式(四)双重校验锁(进阶.懒汉模式)

 1 public class SingleTon {
 2      // 1.自己创建对象,自给自足
 3      private static volatile SingleTon singleTon;
 4      // 2.加上private让外部的其他类无法通过new创建对象,不给别人new
 5      private SingleTon(){} 
 6      // 3.提供一个公共方法给外部,还是要给别人用
 7      public static SingleTon getInstance(){
 8          // 第一个判断是为了在对象存在时不做同步,节省时间
 9          if(singleTon == null){
10              synchronized(SingleTon.class){
11                  // 第二个判断是为了在多线程操作这个方法生成实例对象时不会出现多个
12                  if( singleTon == null){
13                      singleTon = new SingleTon();
14                  }
15              }
16          }
17          return singleTon;
18      }
19  }

这段代码本质上就是比普通.懒汉模式多了一个IF判断,主要是为了在对象存在时直接返回对象不做同步,减少对内存的占用。

优点:线程安全、效率可以、使用时才创建对象                                       缺点:代码多,理解复杂

实现方式(五)静态内部类

 1 public class SingleTon {
 2     // 1.加上private让外部的其他类无法通过new创建对象
 3     private SingleTon(){} 
 4     // 2.静态内部类(创建一个单例对象)
 5     private static class Inner{
 6         private static final SingleTon singleTon = new SingleTon();
 7     }
 8     // 3.获取静态内部类的属性(单例对象)
 9     public static SingleTon getInstance(){
10         return Inner.singleTon;
11     }
12 }

只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。

优点:没用过,不清楚                                               缺点:没看懂,不清楚

实现方式(六)枚举单例模式

1  public enum SingleTon {
2      INSTANCE;
3  }

简单到发指。。。没懂

参考资料:https://www.jianshu.com/p/3bfd916f2bb2

https://baijiahao.baidu.com/s?id=1642521443436643881&wfr=spider&for=pc

https://www.cnblogs.com/renyuanwei/p/9203088.html

原文地址:https://www.cnblogs.com/flyingorchid/p/12534647.html