【php精品源码栏目提醒】:网学会员为需要php精品源码的朋友们搜集整理了【精品】单例模式 - 其它资料相关资料,希望对各位网友有所帮助!
Java 模式设计之单例模式 作为对象的创建模式GOF95, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
这个类称为单例类。
注:本文乃阎宏博士的《Java 与模式》一书的第十五章。
引言 单例模式的要点 单例 显然单例模式的要点有三个;一是某各类只能有一个实例;二是它必须自行创建这个事例;三是它必须自行向整个系统提供这个实例。
在下面的对象图中,有一个quot单例对象quot,而quot客户甲quot、quot客户乙quot 和quot客户丙quot是单例对象的三个客户对象。
可以看到,所有的客户对象共享一个单例对象。
而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。
资源管理 一些资源管理器常常设计成单例模式。
在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个 Printer Spooler, 以避免两个打印作业同时输出到打印机中。
每台计算机可以有若干传真卡,但是只应该有一个软件负责管理传真卡,以避免出现两份传真作业同时传到传真卡中的情况。
每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。
需要管理的资源包括软件内部资源,譬如,大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置。
这样的系统应当由一个对象来管理一个属性文件。
需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等。
这些部件都必须集中管理,不可政出多头。
这些资源管理器构件必须只有一个实例,这是其一;它们必须自行初始化,这是其二;允许整个系统访问自己这是其三。
因此,它们都满足单例模式的条件,是单例模式的应用。
一个例子:Windows 回收站 Windows 9x 以后的视窗系统中都有一个回收站,下图就显示了 Windows 2000 的回收站。
在整个视窗系统中,回收站只能有一个实例,整个系统都使用这个惟一的实例,而且回收站自行提供自己的实例。
因此,回收站是单例模式的应用。
双重检查成例 在本章最后的附录里研究了双重检查成例。
双重检查成例与单例模式并无直接的关系,但是由于很多 C 语言设计师在单例模式里面使用双重检查成例,所以这一做法也被很多 Java 设计师所模仿。
因此,本书在附录里提醒读者,双重检查成例在 Java 语言里并不能成立,详情请见本章的附录。
单例模式的结构 单例模式有以下的特点: .. 单例类只可有一个实例。
.. 单例类必须自己创建自己这惟一的实例。
.. 单例类必须给所有其他对象提供这一实例。
虽然单例模式中的单例类被限定只能有一个实例,但是单例模式和单例类可以很容易被推广到任意且有限多个实例的情况,这时候称它为多例模式(Multiton Pattern) 和多例类(Multiton Class),请见quot专题:多例(Multiton )模式与多语言支持quot一章。
单例类的简略类图如下所示。
由于 Java 语言的特点,使得单例模式在 Java 语言的实现上有自己的特点。
这些特点主要表现在单例类如何将自己实例化上。
饿汉式单例类饿汉式单例类是在 Java 语言里实现得最为简便的单例类,下面所示的类图描述了一个饿汉式单例类的典型实现。
从图中可以看出,此类已经自已将自己实例化。
代码清单 1:饿汉式单例类public class EagerSingletonprivate static final EagerSingleton m_instance new EagerSingleton/ 私有的默认构造子/private EagerSingleton / 静态工厂方法 / public static EagerSingleton getInstance 224Java 与模式 return m_instance 读者可以看出,在这个类被加载时,静态变量 m_instance 会被初始化,此时类的 私有构造子会被调用。
这时候,单例类的惟一实例就被创建出来了。
Java 语言中单例类的一个最重要的特点是类的构造子是私有的,从而避免外界利用 构造子直接创建出任意多的实例。
值得指出的是,由于构造子是私有的,因此,此类不 能被继承。
懒汉式单例类 与饿汉式单例类相同之处是,类的构造子是私有的。
与饿汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化。
如果加载器是静态的,那么在懒汉式单例类被加载时不会将自己实例化。
如下图所示,类图中给出了一个典型的饿汉式单例类实现。
代码清单 2:懒汉式单例类package com.javapatterns.singleton.demospublic class LazySingletonprivate static LazySingletonm_instance null/ 私有的默认构造子,保证外界无法直接实例化/private LazySingleton / 静态工厂方法,返还此类的惟一实例/synchronized public static LazySingletongetInstanceif m_instance nullm_instance new LazySingletonreturn m_instance 读者可能会注意到,在上面给出懒汉式单例类实现里对静态工厂方法使用了同步化,以处理多线程环境。
有些设计师在这里建议使用所谓的quot双重检查成例quot。
必须指出的是,quot双重检查成例quot不可以在 Java 语言中使用。
不十分熟悉的读者,可以看看后面给出的小节。
同样,由于构造子是私有的,因此,此类不能被继承。
饿汉式单例类在自己被加载时就将自己实例化。
即便加载器是静态的,在饿汉式单例类被加载时仍会将自己实例化。
单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。
从速度和反应时间角度来讲,则比懒汉式单例类稍好些。
然而,懒汉式单例类在实例化时, 必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间。
这意味着出现多线程同时首次引用此类的机率变得较大。
饿汉式单例类可以在 Java 语言内实现, 但不易在 C 内实现,因为静态初始化在 C里没有固定的顺序,因而静态的 m_instance 变量的初始化与类的加载顺序没有保证,可能会出问题。
这就是为什么 GoF 在提出单例类的概念时,举的例子是懒汉式的。
他们的书影响之大,以致 Java 语言中单例类的例子也大多是懒汉式的。
实际上,本书认为饿汉式单例类更符合 Java 语言本身的特点。
登记式单例类 登记式单例类是 GoF 为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的。
本书把他们的例子翻译为 Java 语言,并将它自己实例化的方式从懒汉式改为饿汉式。
只是它的子类实例化的方式只能是懒汉式的, 这是无法改变的。
如下图所示是登记式单例类的一个例子,图中的关系线表明,此类已将自己实例化。
代码清单 3:登记式单例类import java.util.HashMappublic class RegSingletonstatic private HashMap m_registry new HashMapstaticRegSingleton x new RegSingletonm_registry.put x.getClass.getName , x/ 保护的默认构造子/protected RegSingleton / 静态工厂方法,返还此类惟一的实例/static public RegSingleton getInstanceString nameif name nullname quotcom.javapatterns.singleton.demos.RegSingletonquotif m_registry.getname nulltrym_registry.put name,Class.forNamename.newInstance catchException eSystem.out.printlnquotError happened.quotreturn RegSingleton m_registry.getname / 一个示意性的商业方法/public Stri
上一篇:
程序员能力矩阵
下一篇:
php论坛毕业论文