单例对象(SingletonMethod)是一种常用的设计模式。单例对象能保证在一个JVM中,该对象只有一个实例存在。
 * 这样的模式有几个好处:
 1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
 2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
 3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。
 (比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
主要缺点:
 1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
 2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
 3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
 如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。


一:

/** 

  * Created by Administrator on 2017-8-23. 

  * 懒汉式,线程不安全 

  * 这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。 

  */ 

 public class SingletonMethod { 

     /** 

      * 持有私有静态实例,防止被引用,此处赋值为null, 

      * 目的是实现延迟加载 

      */ 

     private static SingletonMethod instance=null; 



     /** 

      * 私有构造方法,防止被实例化 

      */ 

     private SingletonMethod(){} 



     /** 

      * 静态工程方法,创建实例 

      */ 

     public static SingletonMethod getInstance(){ 

         if (instance==null){ 

             instance=new SingletonMethod(); 

         } 

         return instance; 

     } 

 }




二:

/** 

  * Created by Administrator on 2017-8-23. 

  * 懒汉式,线程安全 

  *  这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。 

  */ 

 public class SingletonMethod2 { 

     private static SingletonMethod2 instance; 

     private SingletonMethod2(){} 



     public static synchronized SingletonMethod2 getInstance(){ 

         if (instance==null){ 

             instance=new SingletonMethod2(); 

         } 

         return instance; 

     } 

 }



三:

/** 

  * Created by Administrator on 2017-8-23. 

  * 饿汉式 

  * 这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化, 

  * 虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 

  * 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载, 

  * 这时候初始化instance显然没有达到lazy loading的效果。 

  */ 

 public class SingletonMethod3 { 

     private static SingletonMethod3 instance=new SingletonMethod3(); 

     private SingletonMethod3(){} 



     public static SingletonMethod3 getInstance(){ 

         return instance; 

     } 

 }



四:

/** 

  * Created by Administrator on 2017-8-23. 

  * 饿汉,变种 

  * 基于静态 代码块,在实例化或者第一次调用时执行 

  * 既可以延迟加载,又线程安全 

  */ 

 public class SingletonMethod4 { 

     private static SingletonMethod4 instance=null; 

     static { 

         instance=new SingletonMethod4(); 

     } 

      

     private SingletonMethod4(){} 

      

     public static SingletonMethod4 getInstance(){ 

         return instance; 

     } 

 }




五:

/** 

  * Created by Administrator on 2017-8-23. 

  * 静态内部类 

  */ 

 public class SingletonMethod5 { 

     /** 

      * 这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程, 

      * 它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果), 

      * 而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类, 

      * 从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载, 

      * 另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载, 

      * 那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。 



      * 恶汉模式的优化版,在类被装载时,静态内部类并没有被实例化, 

      * 只有getInstance()时才 会装载 SingletonHolder 类,静态内部类方式也能很好地,实现线程安全、高效率和延迟加载特性。 

      */ 

     private static class SingletonHolder{ 

         private static final SingletonMethod5 instance=new SingletonMethod5(); 

     } 



     private SingletonMethod5(){} 



     public static final SingletonMethod5 getInstance(){ 

         return SingletonHolder.instance; 

     } 

 }


六:

/** 

  * Created by Administrator on 2017-8-23. 

  * 枚举 

  *  这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊, 

  *  不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。 

  */ 

 public enum SingletonMethod6 { 

     SINGLETON; 

 }




七:

/** 

  * Created by Administrator on 2017-8-23. 

  * (双重校验锁): 

  * 懒汉模式的优化版,拥有线程安全、高效率以及延迟加载等特性。 

  * 但是这种方式需要jdk1.5以上,且在一些平台和编译器下有错。 

  */ 

 public class SingletonMethod7 { 

     private volatile static SingletonMethod7 singleton; 



     private SingletonMethod7(){} 



     public static SingletonMethod7 getSingleton(){ 

         if (singleton==null){ 

             synchronized (SingletonMethod7.class){ 

                 if (singleton==null){ 

                     singleton=new SingletonMethod7(); 

                 } 

             } 

         } 

         return singleton; 

     } 

 } 

 /**


 * 总结:
 * 1、单例模式理解起来简单,但是具体实现起来还是有一定的难度。
 * 2、synchronized关键字锁定的是对象,在用的时候,一定要在恰当的地方使用(注意需要使用锁的对象和过程,可能有的时候并不是整个对象及整个过程都需要锁)。


 * 采用类的静态方法,实现单例模式的效果,也是可行的,此处二者有什么不同?
 首先,静态类不能实现接口(从类的角度说是可以的,但是那样就破坏了静态了。因为接口中不允许有static修饰的方法,所以即使实现了也是非静态的)
 其次,单例可以被延迟初始化,静态类一般在第一次加载是初始化。之所以延迟加载,是因为有些类比较庞大,所以延迟加载有助于提升性能。
 再次,单例类可以被继承,他的方法可以被覆写。但是静态类内部方法都是static,无法被覆写。
 单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,
 但是静态类不行。从上面这些概括中,基本可以看出二者的区别,


 但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,
 所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。
 两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,
 单用不同的方法来处理问题,总是有优点也有缺点,
 最完美的方法是,结合各个方法的优点,才能最好的解决问题!
 */


github地址:https://github.com/zyj18410105150/DesignMode