单例模式

单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

单例模式(singleton)顾名思义,就是只有一个实例。

 

作为对象的创建模式[GOF95], 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

单例模式的要点

显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。在下面的对象图中,有一个"单例对象",而"客户甲"、"客户乙" 和"客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。

一些资源管理器常常设计成单例模式。

计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。每台计算机可以有若干传真卡,但是只应该有一个软件负责管理传真卡,以避免出现两份传真作业同时传到传真卡中的情况。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。

需要管理的资源包括软件内部资源,譬如,大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置。这样的系统应当由一个对象来管理一个属性文件。

需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等。这些部件都必须集中管理,不可政出多头。

这些资源管理器构件必须只有一个实例,这是其一;它们必须自行初始化,这是其二;允许整个系统访问自己这是其三。因此,它们都满足单例模式的条件,是单例模式的应用。

在java中,可以使用以下这种方式使用单例模式创建类的实例:

public class MyBean {

private static MyBean instance = null;

private MyBean(){

//do something

}

public static synchronized MyBean getInstance(){

if(instance == null){

instance = new MyBean();

}

return instance;

}

}

当一个类的实例可以有且只可以一个的时候就需要用到了。为什么只需要有一个呢?有人说是为了节约内存。本人对这个说法持保留态度。只有一个实例确实减少内存占用,可是我认为这不是使用单例模式的理由。我认为使用单例模式的时机是当实例存在多个会引起程序逻辑错误的时候。比如类似有序的号码生成器这样的东西,怎么可以允许一个应用上存在多个呢?

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

一般Singleton模式通常有两种形式:

第一种形式: 也是常用的形式。

public class Singleton {

private static Singleton instance = null;

private Singleton(){

//do something

}

//这个方法比下面的有所改进,不用每次都进行生成对象,只是第一次使用时生成实例,提高了效率

public static Singleton getInstance(){

if(instance==null){

instance = new Singleton();

}

return instance;

}

}

第二种形式:

public class Singleton {

//在自己内部定义自己的一个实例,只供内部调用

private static Singleton instance = new Singleton();

private Singleton(){

//do something

}

//这里提供了一个供外部访问本class的静态方法,可以直接访问

public static Singleton getInstance(){

return instance;

}

}

Flex中的单例模式

Flex中单例模式,常见的model层实例:

package models

{

import flash.events.EventDispatcher;

import mx.collections.ArrayCollection;

import vo.articlesVO;

import vo.linksVO;

[Bindable]

public class ModelLocator extends EventDispatcher

{

public static var _instance:ModelLocator;

public static function getInstance():ModelLocator{

if(_instance == null){

_instance = new ModelLocator();

}

return _instance;

}

public var total:int;

public var isLogin:Boolean = false;

public var articles:ArrayCollection;

public var selectedArticle:articlesVO;

public var categories:ArrayCollection;

public var links:ArrayCollection;

public var selectedLink:linksVO;

}

}

类中自己完成了自身的实例。。

<mx:Script>

<![CDATA[

import models.ModelLocator;

internal function initApp():void{

var instance:ModelLocator = ModelLocator.getInstance();

trace(instance.isLogin);//获得isLogin

}

]]>

</mx:Script>

C#中的单例模式

#region 用法说明 //保证一个类仅有一个实例,并提供一个访问它的全局访问点

// 实现要点

// Singleton模式是限制而不是改进类的创建。

// Singleton类中的实例构造器可以设置为Protected以允许子类派生。

// Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。

// Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。

// Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。

// 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。

// 可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。

//优点

// 实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例

// 灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

//缺点

// 开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。

// 可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

// 对象的生存期:Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除

//对象实例,但这样会导致 Singleton 类中出现悬浮引用。

//适用性

// 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

// 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

//应用场景

// 每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。

//(摘自吕震宇的C#设计模式(7)-Singleton Pattern)

// PC机中可能有几个串口,但只能有一个COM1口的实例。

// 系统中只能有一个窗口管理器。

// .NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。

#endregion

//regret4hxp add 2011-1-12

单例模式的实现要素:

至少在目前所有了解的语言中,静态变量(这是c/c++的叫法,其他语言或有不同)是实现单例模式的要素。