1.单例模式
作为对像的创建模式【GOF95】,单例模式确保某一类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
要点:
一、是某个类只能有一个实例
二、它必须自行创建这个实例
三、它必须自行向整个系统提供这个实例
如:有个单例对象,而客户甲、客户乙、客户丙是单例对象的三个客户对象。因此,三个客户共享一个单例对象,而且单例对象持有对自身的引用。
(1)资源管理
一些资源管理器常被设计成单例模式。
外部资源
1.每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中
2.每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用
内部资源
1.大多数的软件都有一个或多个属性文件(properties)存放系统配置。这样的系统应当有一个对象来管理一个属性文件。
2.负责记录网站来访的人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等。
这些资源管理器构件必须只有一个实例,必须自行初始化,允许整个系统访问自己。它们都满足单例模式的条件,是单例模式的应用。
一个例子:Windows回收站
windows 9x以后的视窗系统都有一个回收站,在整个视窗系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此,回收站是单例模式的应用。
双重检查成例
双重检查成例与单例模式并无直接关系,但是由于很多C语言设计师在单例模式里面使用双重检查成例,而这一做法也被很多java设计师所模仿。但是双重检查成例在java语言里并不能成立。
由于java语言的特点,使得单例模式在java语言的实现上有自己的特点,这些特点主要表现在单例类如何将自己实例化上。
饿汉式单例类,饿汉式单例类是在java语言里实现最为简便的单例类。
代码清单:饿汉式单例类
public class EagerSingleton{
private static final EagerSingleton m_instance=new EagerSingleton();
/**
*私有的默认构造方法
*/
private EagerSingleton(){};
/**
*静态工厂方法
*
*/
public static EagerSingleton getInstance(){
return m_instance;
}
}
我们可以看出,在这个类被加载时,静态变量m_instance会被初始化,此时类的私有构造方法会被调用。这时候,单例类的唯一实例就被创建出来了。
java语言中单列类的一个重要的特点是类的构造方法是私有的,从而避免外界利用构造方法直接创建出任意多的实例。值得指出的是,由于构造方法是私有的,因此,此类不能被继承。
懒汉式单例类
与饿汉式单例类相同之处是,类的构造方法是私有的。不同的是,懒汉式单例类在第一次被引用时将自己实例化。如果加载器是静态的,那么在懒汉式单例类被加载时不会将自己实例化。
代码清单:懒汉式单例类
public class LazySingleton{
private static LazySingleton m_instance=null;
/**
*私有的默认构造方法,保证外界无法直接实例化
*/
private LazySingleton{}
/**
*静态工厂方法,返回此类的唯一实例
*/
synchronized public static LazySingleton getInstance(){
if(m_instance==null){
m_instance=new LazySingleton();
}
return m_instance;
}
}
我们可以注意到,在上面给出懒汉式单例类实现里面对静态工厂方法使用了同步化,以处理多线程环境。有些设计师在这里建议使用所谓的“双重检查成例”。必须指出的是,“双重检查成例”不可以在java语言中使用。
饿汉式单例类被加载时就将自己实例化,单从资源利用效率角度来讲,比懒汉式单例类稍差些。
从速度和反应时间,懒汉式单例类稍差些。然而,懒汉式单例类在实例化时,必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间,这意味着出现多线程同时首次引用此类的几率变的较大。
饿汉式单例类可以在java语言内实现,但不易在c++内实现,因为静态初始化在c++里没有固定的顺序,因而静态m_instanse变量的初始化与类的加载顺序没有保证,可能会出问题。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。