面向对象设计模式点滴(2)之Singleton
意图:保证一个类仅有一个实例,并提供一个该实例的安全访问点。举不太正确的例子,例如防火墙(有谁能将同一防火墙开两次?),当然这里的“谁”不一定是客户(人),而是客户程序,调用该实例的程序。
错误的看法有人说,new一次不就行了吗?保证不new第二次就行!
这样做不好,如果要每一个调用该实例的客户程序都保证只new一次,是否会很麻烦?也很不安全。我们将这个“只生成一个实例”的需求交由类的设计者本身保证,那么调用该实例的若干客户程序会省下大堆麻烦和安全隐患。
Demo:
class Singleton
{
private static Singleton instance;
// Constructor
private Singleton() {}//关键之中的关键,如果没有构造函数,C#编译器会默认为public Singleton()
//私有构造函数,这样做就可以防止其他类,想new就new ,也可以protected来允许派生类调用
public static Singleton Instance()
{
//通常 使用晚加载,用户调用了Singleton.Instance()才new一个实例
if( instance == null )
instance = new Singleton();
return instance;
}//只有在本类中才能new一个实例,如果有实例
//存在,则返回自己
}通过上面的Demo,有一下几点使用总结:
1 应用在单线程中,非多线程,显而易见,如果线程B在线程A没有new之前执行判断语句
if( instance == null ),则线程B又会new一个instance。
2 Singleton只考虑了对象创建管理,没考虑垃圾回收。这并不是该模式的局限性,而是没必要考虑
,只有一个实例,占用不了多少资源。如果类大得不回收不行,则要重构了。
3 一般不支持序列化(序列化的实现还不太明白,这里先跳过去)
多线程的应用:
希望各位帮帮忙解答:
using System;
using System.Threading;
class Singleton
{
private static volatile Singleton instance;
private static object lockHelper=new Object();
protected Singleton() {}
public static Singleton Instance()
{
if( instance == null )
{
lock(lockHelper)
{
if( instance == null )
{
instance = new Singleton();
}
}
}
// if( instance == null )
// {
// instance = new Singleton();
// }
return instance;
}
}
![](/Images/OutliningIndicators/None.gif)
public class Client
{
private static Singleton s1;
private static Singleton s2;
static public void dosomwork1()
{
s1=Singleton.Instance();
}
static public void dosomwork2()
{
s2=Singleton.Instance();
}
public static void Main()
{
Thread t1=new Thread(new ThreadStart(dosomwork1));
Thread t2=new Thread(new ThreadStart(dosomwork2));
t1.Start();
t2.Start();
if( s1 == s2 )
Console.WriteLine( "The same instance" );
else
Console.WriteLine( "The different instance" );
}
}问题1:为什么直接执行显示The same instance,(将断点放在t1.Start();=......,且逐行执行)的时候显示是The different instance?我已经使用了double check lock啦。
问题2:有什么办法在单重判断的时候显示出The different instance吗?
错误的看法有人说,new一次不就行了吗?保证不new第二次就行!
这样做不好,如果要每一个调用该实例的客户程序都保证只new一次,是否会很麻烦?也很不安全。我们将这个“只生成一个实例”的需求交由类的设计者本身保证,那么调用该实例的若干客户程序会省下大堆麻烦和安全隐患。
Demo:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
1 应用在单线程中,非多线程,显而易见,如果线程B在线程A没有new之前执行判断语句
if( instance == null ),则线程B又会new一个instance。
2 Singleton只考虑了对象创建管理,没考虑垃圾回收。这并不是该模式的局限性,而是没必要考虑
,只有一个实例,占用不了多少资源。如果类大得不回收不行,则要重构了。
3 一般不支持序列化(序列化的实现还不太明白,这里先跳过去)
多线程的应用:
希望各位帮帮忙解答:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
问题2:有什么办法在单重判断的时候显示出The different instance吗?