单例对象(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