单件模式
单件模式是一种用于确保整个应用程序中只有一个类实例且这个实例所占资源在整个应用程序中是共享时的程序设计方法(根据实际情况,可能需要几个类实例)。在某些情况下,这种程序设计方法是很有用处的。
目录
设计模式-单件模式(singleton)
单件模式应该使用在什么场合
单件模式类的创建
Singleton模式的实现
设计模式-单件模式(singleton)
单件模式应该使用在什么场合
单件模式类的创建
Singleton模式的实现
展开
设计模式-单件模式(singleton)
单件模式应该使用在什么场合
当需要控制一个类的实例数量且调用者可以从一个公共的众所周知的访问点访问时。
单件模式类的创建
我们分两种方式来讨论一个单件类的创建,一是将一个类的公共构造函数改为私有,另一种方式是保留类的公共构造函数,通过一个静态成员来决定是否要返回一个类实例。
Singleton模式
Singleton可以说是《Design Pattern》中最简单也最实用的一个设计模式。那么,什么是Singleton?
顾名思义,Singleton就是确保一个类只有唯一的一个实例。Singleton主要用于对象的创建,这意味着,如果某个类采用了Singleton模式,则在这个类被创建后,它将有且仅有一个实例可供访问。很多时候我们都会需要Singleton模式,最常见的比如我们希望整个应用程序中只有一个连接数据库的Connection实例;又比如要求一个应用程序中只存在某个用户数据结构的唯一实例。我们都可以通过应用Singleton模式达到目的。
一眼看去,Singleton似乎有些像全局对象。但是实际上,并不能用全局对象代替Singleton模式,这是因为:其一,大量使用全局对象会使得程序质量降低,而且有些编程语言例如C#,根本就不支持全局变量。其二,全局对象的方法并不能阻止人们将一个类实例化多次:除了类的全局实例外,开发人员仍然可以通过类的构造函数创建类的多个局部实例。而Singleton模式则通过从根本上控制类的创建,将"保证只有一个实例"这个任务交给了类本身,开发人员不可能再有其它途径得到类的多个实例。这一点是全局对象方法与Singleton模式的根本区别。
编辑本段Singleton模式的实现
Singleton模式的实现基于两个要点:
1)不直接用类的构造函数,而另外提供一个Public的静态方法来构造类的实例。通常这个方法取名为Instance。Public保证了它的全局可见性,静态方法保证了不会创建出多余的实例。
2)将类的构造函数设为Private,即将构造函数"隐藏"起来,任何企图使用构造函数创建实例的方法都将报错。这样就阻止了开发人员绕过上面的Instance方法直接创建类的实例。
通过以上两点就可以完全控制类的创建:无论有多少地方需要用到这个类,它们访问的都是类的唯一生成的那个实例。以下C#代码展现了两种实现Singleton模式的方式,开发人员可以根据喜好任选其一。
实现方式一:Singleton.cs
using System;
class SingletonDemo
{ private static SingletonDemo theSingleton = null;
private SingletonDemo() {}
public static SingletonDemo Instance()
{ if (null == theSingleton)
{
theSingleton = new SingletonDemo();
}
return theSingleton;
}
static void Main(string[] args)
{ SingletonDemo s1 = SingletonDemo.Instance();
SingletonDemo s2 = SingletonDemo.Instance();
if (s1.Equals(s2))
{ Console.WriteLine("see, only one instance!");
}
}
}
与之等价的另外一种实现方式是:Singleton.cs:
using System;
class SingletonDemo
{ private static SingletonDemo theSingleton = new SingletonDemo();
private SingletonDemo() {}
public static SingletonDemo Instance()
{ return theSingleton;
}
static void Main(string[] args)
{ SingletonDemo s1 = SingletonDemo.Instance();
SingletonDemo s2 = SingletonDemo.Instance();
if (s1.Equals(s2))
{ Console.WriteLine("see, only one instance!");
}
}
}
编译执行:
Csc Singleton.cs
得到运行结果:
see, only one instance!
.NET中的Singleton
因为Singleton模式具有这样实用的价值,开发人员除了可以在程序代码中直接使用Singleton模式外,在许多大型系统的实现上也都处处可见它的影子。在微软隆重推出的.NET框架中,同样也可以发现Singleton思想闪烁的光芒。
举例来说,在.NET框架的重要组成部分Remoting中,远程对象(Remote Object)有两种激活方式:服务器端激活方式和客户端激活方式。采用服务器端激活方式的对象又分为两种类型:Singleton对象和SingleCall对象。Singleton 对象是这样的对象:无论该对象有多少个客户端调用,它总是只有一个实例,由这个实例来处理所有的客户端请求。相反地,若将远程对象声明为 SingleCall,则系统会为每次客户端方法的调用创建一个新对象,即使这些方法调用来自同一个客户端,也即,对象只在方法调用持续期间存在,一旦方法调用结束,该对象就会被销毁。显而易见,这里的Singleton对象就是设计模式Singleton思想在.NET中的应用。
那么,如何在.NET的Remoting中利用Singleton?.NET提供了两种方式将一个远程对象注册为Singleton:直接调用RegisterWellKnownServiceType方法,在参数中指定对象类型为Singleton;或在配置文件web.config中设定远程对象的类型为Singleton。这两种方法的效果相同,所不同的是后一种方法显得更加方便,因为改变配置文件的内容后,不必重新编译应用程序。下列代码显示了如何使用RegisterWellKnownServiceType方法注册远程对象类型:
RemotingConfiguration.RegisterWellKnownServiceType( Type.GetType("RemotingSamples.HelloServer,object"), "SayHello", WellKnownObjectMode.Singleton);
参数"SayHello"是客户端访问远程对象(这里是HelloServer)时用来代表远程对象的URI,例如tcp://localhost:8085/SayHello(假设使用的是TCP通道)。
最后一个参数就指明了这个远程对象是Singleton类型。一旦将远程对象注册为Singleton,则在第一次客户端调用HelloServer的方法时创建这个远程对象,然后保持它直到客户端中断连接或对象超时被销毁为止。在此期间,无论有多少个客户端调用这个远处对象,所有的客户请求都将由那个已经存在的唯一实例接受处理。
这就是Singleton在.NET中的应用。
从Singleton模式的实现和应用中也可以看出,优秀的设计模式往往都具有"简约之美"。它们采用一种"优雅"的方式,将那些成功的设计方法和体系结构能够得以被简单、方便地复用。这也是为什么现在的软件开发日益强调"设计模式"的原因之所在。如果想进一步了解更多的设计模式,还是推荐各位阅读Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides的经典之作《Design Pattern》