读书人

研磨设计方式之单例模式-2

发布时间: 2012-11-14 10:12:19 作者: rapoo

研磨设计模式之单例模式-2

3? 模式讲解3.1? 认识单例模式

(1)单例模式的功能
??????? 单例模式的功能是用来保证这个类在运行期间只会被创建一个类实例,另外单例模式还提供了一个全局唯一访问这个类实例的访问点,就是那个getInstance的方法。不管采用懒汉式还是饿汉式的实现方式,这个全局访问点是一样的。
??????? 对于单例模式而言,不管采用何种实现方式,它都是只关心类实例的创建问题,并不关心具体的业务功能。
(2)单例模式的范围
??????? 也就是在多大范围内是单例呢?
??????? 观察上面的实现可以知道,目前Java里面实现的单例是一个ClassLoader及其子ClassLoader的范围。因为一个ClassLoader在装载饿汉式实现的单例类的时候就会创建一个类的实例。
??????? 这就意味着如果一个虚拟机里面有很多个ClassLoader,而且这些ClassLoader都装载某个类的话,就算这个类是单例,它也会产生很多个实例。当然,如果一个机器上有多个虚拟机,那么每个虚拟机里面都应该至少有一个这个类的实例,也就是说整个机器上就有很多个实例,更不会是单例了。
??????? 另外请注意一点,这里讨论的单例模式并不适用于集群环境,对于集群环境下的单例这里不去讨论,那不属于这里的内容范围。
(3)单例模式的命名
??????? 一般建议单例模式的方法命名为:getInstance(),这个方法的返回类型肯定是单例类的类型了。getInstance方法可以有参数,这些参数可能是创建类实例所需要的参数,当然,大多数情况下是不需要的。
??????? 单例模式的名称:单例、单件、单体等等,翻译的不同,都是指的同一个模式。


3.2? 懒汉式和饿汉式实现

??????? 前面提到了单例模式有两种典型的解决方案,一种叫懒汉式,一种叫饿汉式,这两种方式究竟是如何实现的,下面分别来看看。为了看得更清晰一点,只是实现基本的单例控制部分,不再提供示例的属性和方法了;而且暂时也不去考虑线程安全的问题,这个问题在后面会重点分析。
1:第一种方案 懒汉式
(1)私有化构造方法
??????? 要想在运行期间控制某一个类的实例只有一个,那首先的任务就是要控制创建实例的地方,也就是不能随随便便就可以创建类实例,否则就无法控制创建的实例个数了。现在是让使用类的地方来创建类实例,也就是在类外部来创建类实例。
??????? 那么怎样才能让类的外部不能创建一个类的实例呢?很简单,私有化构造方法就可以了!示例代码如下:


??????????????????????? 图2? 懒汉式调用顺序示意图

饿汉式的调用顺序,如图3所示:

研磨设计方式之单例模式-2
????????????????????????????? ?图3? 饿汉式调用顺序示意图

?

?

?

??? 未完待续

15 楼 chjavach 2010-08-02 juda 写道楼主,上次有个哥们给你画了个图,那个工具你问到没?

我也是在评论里面问了一下,哪个哥们没有回,我再发信息问问看. 16 楼 chjavach 2010-08-05 juda 写道楼主,上次有个哥们给你画了个图,那个工具你问到没?

问到了,是 edraw 也就是 亿图 17 楼 kind790 2010-08-18 //线程安全-仅限懒汉模式
public static Singleton getInstance(){
//先判断instance是否有值
if(instance == null){
synchronized (Singleton.class) {
//如果没有值,说明还没有创建过实例,那就创建一个
//并把这个实例设置给instance
if(instance == null){
instance = new Singleton ();
}
}
}
//如果有值,或者是创建了值,那就直接使用
return instance;
}
18 楼 found_method 2010-08-26 kind790 写道//线程安全-仅限懒汉模式
public static Singleton getInstance(){
//先判断instance是否有值
if(instance == null){
synchronized (Singleton.class) {
//如果没有值,说明还没有创建过实例,那就创建一个
//并把这个实例设置给instance
if(instance == null){
instance = new Singleton ();
}
}
}
//如果有值,或者是创建了值,那就直接使用
return instance;
}


你的这个写法不是真正的线程安全,if语句的执行不是原子的,synchronized要加在if语句前,或者方法声明处 19 楼 lucky16 2010-09-08 第一次看见有人解释设计模式这么详细的!
很感谢LZ精彩的文采和简单易懂的举例!

期待你的下一次更新,

顺便问一句楼主, 你觉得作为一个Java EE程序员, 必须熟练掌握的几种设计模式是 ? ? 20 楼 runshine 2010-09-09 不错,说的很详细
不过关于单例模式的范围的描述可能有点偏差.
单例模式的范围是一个ClassLoader及其子ClassLoader而非整个JVM.
在这里我做了详细描述.
http://www.iteye.com/topic/753903 21 楼 chjavach 2010-09-13 runshine 写道不错,说的很详细
不过关于单例模式的范围的描述可能有点偏差.
单例模式的范围是一个ClassLoader及其子ClassLoader而非整个JVM.
在这里我做了详细描述.
http://www.iteye.com/topic/753903

你说得很对,单例的范围是一个ClassLoader及其子ClassLoader,文中也提到了这一点。但是在写这篇文章的时候,只考虑了一个虚拟机一个ClassLoader的情况,所以就描述成JVM了,而一个虚拟机是可以有很多的ClassLoader的,因而文中的的描述是不够准确的。

谢谢你的指正,非常感谢! 22 楼 chjavach 2010-09-13 已经修正,再次感谢 runshine ! 23 楼 浪客剑心 2010-10-24 chjavach 写道已经修正,再次感谢 runshine !
见过设计模式写得详细的,没有见过像楼主这么详细的,赞一个!
另外,一个小小建议:
楼主在修改的地方,把修改前的内容保留,做一下注释,这样我们也可以对照着看一下。

像其他人一样期待楼主有更好的文章,不止设计模式方面的。

读书人网 >软件开发

热点推荐