单件模式:浅析软件Software项目开发中的单件模式

  前言

  单件(Singleton)模式作为设计模式个典型且相对简单构造型模式已经在很多项目实际开发中被广泛采用由于其所有相关操作都是基于同个例子引用因此单件模式使用主要出于如下几个目:

  逻辑上仅仅只有个例子才可以保证逻辑正确性

  减少频繁构造过程带来应用上性能损失

  下面是个最简单经典单件模式实现方式:

using ;
VisionLogic.DesignPattern.Practice
...{
public Singleton
...{
private Singleton instance;
private Singleton ...{ }
public Singleton Instance
...{
get
...{
(instance null)
...{
instance = Singleton;
instance.data = 0;
}
instance;
}
}
/**//// <summary>
/// 共享例子数据
/// </summary>
private data;
public Data
...{
get ...{ data; }
...{ data = value; }
}
}
}
  举例1

  那么客户端在实际使用中通过静态Instance属性就可以获得个唯例子无论哪个客户对于引用例子操作都会在其他客户中同步更新

using ;
using .Diagnostics;
using VisionLogic.DesignPattern.Practice;
VisionLogic.DesignPattern.Practice.Client
...{
Program
...{
void Main( args)
...{
Singleton instance1 = Singleton.Instance;
Singleton instance2 = Singleton.Instance;
instance1.Data = 30;
Trace.WriteLine(instance2.Data);
instance2.Data = 15;
Trace.WriteLine(instance1.Data);
}
}
}
结果:
30
15
  举例2

  单件模式主要注意事项

  上面例子虽然简单但实际使用中还需要考虑不要面向对象特性和新开发平台特性所导致单件类型性质变异

  不要实现ICloneable接口或者继承自其相关子类否则客户可以跳过已经隐蔽起来类构造导致私有Singleton { } 部分实效

using ;
VisionLogic.DesignPattern.Practice
...{
public BaseEntity : ICloneable
...{
public object Clone
...{
this.MemberwiseClone;
}
}
public Singleton : BaseEntity
...{
private Singleton instance;
private Singleton ...{ }
public Singleton Instance
...{
get
...{
(instance null)
...{
instance = Singleton;
instance.data = 0;
}
instance;
}
}
…. 
}
} 
  举例3

using ;
using .Diagnostics;
using VisionLogic.DesignPattern.Practice;
VisionLogic.DesignPattern.Practice.Client
...{
Program
...{
void Main( args)
...{
Singleton instance1 = Singleton.Instance;
Singleton instance2 = (Singleton)instance1.Clone;
instance1.Data = 30;
Trace.WriteLine(instance2.Data);
instance2.Data = 15;
Trace.WriteLine(instance1.Data);
}
}
}
结果:
0
30
  举例4

  上面举例介绍说明通过ICloneable接口克隆过程导致私有构造失效CLR通过内存结构复制生成了个新例子最终导致区别例子引用操作结果各自独立

  上面单件实现虽然采取了无参数私有构造但是实际工程中对于第个且唯个例子构造可能会依赖于具体参数不过由于每个客户在真正使用时使用都是既得例子因此实际上客户不应该把构造参数传递给唯个例子构造实际参数传递过程般只能通过硬编码在单件类型静态属性Instance中完成考虑到代码维护性问题笔者建议保留例子无参数构造而把需要传递参数通过配置系统传递到唯例子构造例如这里增加了 3个配置值:

<configuration>
<configSections>
<section name="sampleSection"
type=".Configuration.SingleTagSectionHandler" />
</configSections>
<sampleSection ting1="Value1"
ting2="value two"
ting3="third value" />
</configuration>
  举例5

  作为个集中访问单独例子有时候常常需要对于自身数据进行更新更新方式可以通过外部显示或者单件例子对象自主更新方式两种方式完成

  如果准备采用外部那么工程上最好通过增加个接口(例如:名为 IRefershable)为应用中每个Singleton类型统增加更新可能和上个介绍说明同理这里刷新过程也最好统设计为无参数思路方法待刷新所需要数据源最好来自于个配置文件或者来自运行环境

using ;
VisionLogic.DesignPattern.Practice
...{
/**//// <summary>
/// 为Singleton 对象增加可以更新能力
/// </summary>
erface IRefershable
...{
void Refersh;
}
Singleton : IRefershable
...{
...
}
}
  举例6

  内部方式则是可以为其增加.Threading.Timer或者通过配置文件Watcher回调代理完成下面是个增加了Timer内部自发更新举例:

using ;
VisionLogic.DesignPattern.Practice
...{
public Singleton
...{
private Singleton instance;
private .Threading.Timer timer;
private const Interval = 2000;
private Singleton ...{ }
public Singleton Instance
...{
get
...{
(instance null)
...{
instance = Singleton;
instance.timeStamp = .DateTime.Now;
instance.timer = .Threading.Timer(
instance.RefershTimeStamp,
null,
0,
Interval);
}
instance;
}
}
/**//// <summary>
/// 共享例子数据
/// </summary>
private DateTime timeStamp;
public DateTime TimeStamp
...{
get ...{ timeStamp; }
}
/**//// <summary>
/// timer 回调思路方法
/// </summary>
/// <param name="state"></param>
private void RefershTimeStamp(object state)
...{
timeStamp = .DateTime.Now;
}
}
}
  举例7

  对于较为大型应用般部署上会考虑采用NLB集群这样如果Singleton其中需要保存些公共内存对象(例如:计数器)但是由于在每个服务器节点上各自都有Singleton所以总体来看Singleton并不“单件”那么应用对于单例子依赖会物理节点非“单件”破坏从本质上讲采用Singleton模式本身会对于应用水平扩展(Scale Out)形成障碍

  如果工程上要对NLB集群中Singleton对象继续保持其“单件”那么可以采用集中保存其属性信息(或State信息)不仅如此对于如果需要通过外界修改这些属性那么还需要在外部增加个串行集中属性信息更新机制



  图:通过只读静态构造完成单件模式编译结果

  其中请注意. public auto ansi beforefieldinit部分它等于CLR内置静态构造机制帮助我们完成了加锁过程确保了只有静态对象在默认提供静态构造器创建的前例子所有属性不能够被访问而唯例子静态Instance则可以安安稳稳地在默认静态构造器中创建下面是编译器生成静态构造



.method private hidebysig specialname rtspecialname
void .cctor cil managed
...{
// Code size    11 (0xb)
.maxstack 8
IL_0000: obj    
instance void VisionLogic.DesignPattern.Practice.Singleton::.ctor
IL_0005: stsfld    
VisionLogic.DesignPattern.Practice.Singleton      
VisionLogic.DesignPattern.Practice.Singleton::Instance
IL_000a: ret
} // end of method Singleton::.cctor




Tags:  单件流 被套单件 单件模式

延伸阅读

最新评论

发表评论