1700456963
1700456964
private Singleton(){
1700456965
1700456966
}
1700456967
1700456968
//通过该方法获得实例对象
1700456969
1700456970
public static Singleton getSingleton(){
1700456971
1700456972
if(singleton==null){
1700456973
1700456974
singleton=new Singleton();
1700456975
1700456976
}
1700456977
1700456978
return singleton;
1700456979
1700456980
}
1700456981
1700456982
}
1700456983
1700456984
该单例模式在低并发的情况下尚不会出现问题,若系统压力增大,并发量增加时则可能在内存中出现多个实例,破坏了最初的预期。为什么会出现这种情况呢?如一个线程A执行到singleton=new Singleton(),但还没有获得对象(对象初始化是需要时间的),第二个线程B也在执行,执行到(singleton==null)判断,那么线程B获得判断条件也是为真,于是继续运行下去,线程A获得了一个对象,线程B也获得了一个对象,在内存中就出现两个对象!
1700456985
1700456986
解决线程不安全的方法很有多,可以在getSingleton方法前加synchronized关键字,也可以在getSingleton方法内增加synchronized来实现,但都不是最优秀的单例模式,建议读者使用如代码清单7-3所示的方式(有的书上把代码清单7-3中的单例称为饿汉式单例,在代码清单7-4中增加了synchronized的单例称为懒汉式单例)。
1700456987
1700456988
其次,需要考虑对象的复制情况。在Java中,对象默认是不可以被复制的,若实现了Cloneable接口,并实现了clone方法,则可以直接通过对象复制方式创建一个新对象,对象复制是不用调用类的构造函数,因此即使是私有的构造函数,对象仍然可以被复制。在一般情况下,类复制的情况不需要考虑,很少会出现一个单例类会主动要求被复制的情况,解决该问题的最好方法就是单例类不要实现Cloneable接口。
1700456989
1700456990
1700456991
1700456992
1700456994
设计模式之禅 7.4 单例模式的扩展
1700456995
1700456996
如果一个类可以产生多个对象,对象的数量不受限制,则是非常容易实现的,直接使用new关键字就可以了,如果只要有一个对象,使用单例模式就可以了,但是如果要求一个类只能产生两三个对象呢?该怎么实现?我们还以皇帝为例来说明。
1700456997
1700456998
一般情况下,一个朝代的同一个时代只有一个皇帝,那有没有出现两个皇帝的情况呢?确实有,就出现在明朝,那三国期间的算不算?不算,各自称帝,各有各的地盘,国号不同。大家还记得《石灰吟》这首诗吗?作者是谁?于谦。他是被谁杀死的?明英宗朱祁镇。对,就是那个在土木堡之变中被瓦刺俘虏的皇帝,被俘虏后,他弟弟朱祁钰当上了皇帝,就是明景帝,估计刚当上皇帝乐疯了,忘记把他哥哥朱祁镇升级为太上皇,在那个时期就出现了两个皇帝,这期间的的大臣是非常郁闷的,为什么呀?因为可能出现今天参拜的皇帝和昨天的皇帝不相同,昨天给那个皇帝汇报,今天还要给这个皇帝汇报一遍,该情况的类图如图7-3所示。
1700456999
1700457000
1700457001
1700457002
1700457003
图7-3 多个皇帝类图
1700457004
1700457005
这个类图看起来还算简单,但是实现就有点复杂了。Emperor类如代码清单7-5所示。
1700457006
1700457007
代码清单7-5 固定数量的皇帝类
1700457008
1700457009
public class Emperor{
1700457010
1700457011
//定义最多能产生的实例数量
1700457012
[
上一页 ]
[ :1.700456963e+09 ]
[
下一页 ]