ObjectBuilder之创建策略祥解(二)
-Written by 浪子
2、单件实例策略(SingletonStrategy):
预备知识:
在使用单件实例策略(SingletonStrategy),必需要先了解ObjectBuilder的另2个模块:
A、 定位器Locator:
关于定位器的原理及实现不在本文的讨论内容,请参考niwalker的专栏之和 之
B、生存周期ILifetimeContainer:
LifetimeContainer主要用来跟踪对象的生存周期,负责对象的销毁动作。我们在这里只要将它当成一个简单的对象容器来用就可以了,类似Hashtable。
单件实例策略:
策略方针:
public class SingletonPolicy : ISingletonPolicy
{
private bool isSingleton;
public SingletonPolicy(
bool isSingleton)
{
this.isSingleton = isSingleton;
}
public bool IsSingleton
{
get {
return isSingleton; }
}
}
可见SingletonPolicy很简单只是设置了一个标识。这个标识将在对象创建中决定是否采用单件实例策略
单件策略:
public class SingletonStrategy : BuilderStrategy
{
public override object BuildUp(IBuilderContext context, Type typeToBuild,
object existing,
string idToBuild)
{
DependencyResolutionLocatorKey key =
new DependencyResolutionLocatorKey(typeToBuild, idToBuild);
// 当前定位器不能为空,并且定位当前节点包含此对象 if (context.Locator !=
null && context.Locator.Contains(key, SearchMode.Local))
{
TraceBuildUp(context, typeToBuild, idToBuild, "");
// 返回在定义器当前节点中key值符合的对象 return context.Locator.Get(key);
}
// 没有则,继续执行一步创建策略 return base.BuildUp(context, typeToBuild, existing, idToBuild);
}
}
我想细心的你一定发现了,这里面跟TypeMappingStrategy中不一样的地方了:
SinglotenPolicy不见了?那是否SinglotenStrategy不需要具体方针呢?起初我也这样认为,后来发现错了。
我们将眼光跳到CreationStrategy,我发现对象创建完之后会执行RegisterObject,将对象注册到定位器&生存周期容器里面。
private void RegisterObject(IBuilderContext context, Type typeToBuild,
object existing,
string idToBuild)
{
if (context.Locator !=
null)
{
ILifetimeContainer lifetime = context.Locator.Get<ILifetimeContainer>(
typeof(ILifetimeContainer), SearchMode.Local);
// 设置了对象生存周期容器 if (lifetime !=
null)
{
SingletonPolicy singletonPolicy = context.Policies.Get<ISingletonPolicy>(typeToBuild, idToBuild);
// 看这里用到了单件实例的具体方针,并确判断是否要启用单件实例 if (singletonPolicy !=
null && singletonPolicy.IsSingleton)
{
// 注册到上下文的定位器 context.Locator.Add(
new DependencyResolutionLocatorKey(typeToBuild, idToBuild), existing);
// 注册到对象生存周期容器 lifetime.Add(existing);
if (TraceEnabled(context))
TraceBuildUp(context, typeToBuild, idToBuild, Properties.Resources.SingletonRegistered);
}
}
}
}
这里好像显得有点藕断丝连了,因为单件实例的策略方针跑到创建策略里面去起作用了:)。
先不管是否是松耦合,不过也可以看出,
ObjectBuilder对象的创建策略如何起作用都是通过各自相对的具体方针决定的。
应用实例:
我们还是利用的实例进行改造:
具体代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.ObjectBuilder;
namespace TestBuilder
{
class Program
{
static void Main(
string[] args)
{
IReadWriteLocator locator;
Builder builder =
new Builder();
PolicyList policyList =
new PolicyList();
policyList.Set<ITypeMappingPolicy>(
new TypeMappingPolicy(
typeof(MyConcreteClass), "myclass"),
typeof(MyAbstractClass), "myclass");
policyList.Set<ISingletonPolicy>(
new SingletonPolicy(
true),
typeof(MyConcreteClass), "myclass");
locator =
new Locator();
LifetimeContainer lifetime =
new LifetimeContainer();
locator.Add(
typeof(ILifetimeContainer),lifetime);
Console.WriteLine("-----------------------");
Console.WriteLine(" 第一次创建对象:");
Console.WriteLine("-----------------------");
MyAbstractClass myclass = builder.BuildUp<MyAbstractClass>(locator, "myclass",
null, policyList);
myclass.Base = "是我啊,还是我!";
Console.WriteLine(myclass.GetType().ToString());
Console.WriteLine(myclass.Base);
Console.WriteLine("-----------------------");
Console.WriteLine(" 第二次创建对象:");
Console.WriteLine("-----------------------");
MyAbstractClass myclass2 = builder.BuildUp<MyAbstractClass>(locator, "myclass",
null, policyList);
Console.WriteLine(myclass2.GetType().ToString());
Console.WriteLine(myclass2.Base);
Console.ReadLine();
}
}
public abstract class MyAbstractClass
{
private string mBase;
public string Base
{
get {
return this.mBase; }
set {
this.mBase = value; }
}
}
public class MyConcreteClass : MyAbstractClass
{
// private string mTest;
}
}
看到这里,我想你应该知道如何应用它,或者你也知道你能怎么去用它了。
比如维护一个类似全局变量的对象集合?
Updated @ 2006.07.04
最近在做Web MVP架构的搭建,准备使用ObjectBuilder来组织对象的创建.
重温了一下ObjectBuilder的单件策略.用自己的理解自己的语言总结了一下:
创建一个对象,并把他缓存起来(对象池,类似连接池),等下一次需要创建相同对象的时候,再把这个对象取出来,而不是重新创建一个.(此时有一个疑问,如果是引用类型的,旧对象中的修改是否会影响到后面再次利用的对象的值)