ObjectBuilder之设计模式(一):策略模式
-Written by 浪子
摘要:
剑是剑,刀是刀。
剑可以杀人,刀也可以杀人,所以它们都能杀人。
不管拿在手里的是剑,还是刀,只要告诉它杀人,它自己会选择合适的方式:剑刺,刀劈……
前言:
回顾“ObjectBuilder内功心法之中国特色”一文之办证部门:
ObjectBuilder 之创建策略(BuilderStrategy) :
首先,需要符合一定的规范才能参与对象的创建流程,犹如必须拥有办证职能的部门才能参与办证的流程一样。
创建策略接口规范,必须有创建方法(BuildUp)、销毁方法(TearDown):
有了指导策略之后,为了处理方便,我们先暂定一些基础的参考方法:定义一个抽象的创建策略基类
“当手头的项目越来越大,对象也越来越多,对象之间的交互也越来越复杂,这时,简单的对象创建过程已经渐渐的不能适应这种情况了。比如,对象之间存在着依赖关系,那么对象的创建次序就显得很重要。一个对象被创建,需要哪些条件?”
有些事情往往看起来简单,但是实际操作起来可能完全不是想象的那样,好比办一张身份证,收到办证通知之后,去人才中心领取户口页,再去指定照相馆照证件照、交钱,然后一段时间后才能到户口所在公安局用旧证换回新证。但是手续再多,我需要去的这些部门肯定都更办证有关,也就都具有办证的职能。
此时,创建的过程就会分出好多阶段PreCreation(预创建阶段)、Creation(创建阶段)、Initialization(对象初始化阶段)、PostInitialization(初始化完成阶段),每个阶段会做些具体的创建过程,但是不管怎么创建,它们都必须符合创建策略接口规范,必须有创建方法(BuildUp)、销毁方法(TearDown):
预创建阶段:
TypeMappingStrategy : 类型映射策略
SingletonStrategy: 单例策略
ConstructorReflectionStrategy: 构造器反射策略
PropertyReflectionStrategy: 属性反射策略
MothodReflectionStrategy: 方法反射策略
创建阶段:
CreationStrategy: 创建策略
初始化阶段:
PropertySetterStrategy: 属性设置器策略
MothodExecutionStrategy: 方法执行策略
初始化完成阶段:
BuilderAwareStrategy: 创建器感知策略
办证的部门越多,各个部门有各自需要做的事情,如果没有一个统一的指导方针,顶层的领导将一无所知,整个办证的过程就陷入混乱状况。所以作为顶层的领导将会发布一个做事的方针规范(办证方针),做到 “上有政策”。 而因为各个部门的实际情况不一样,所以遵循着领导的指示之外,还需要做适当的融会贯通,正所谓“下有对策”。
当过程越来越复杂,参与的对象也越来越多,同样也需要做到“上有政策,下有对策”。
定义对象创建方针,是个空接口
各个具体创建策略创建自己的具体创建方针
每个具体的创建策略在创建对象的时候调用自己的具体创建方针:
{
public override object BuildUp(IBuilderContext context, Type t, object existing, string id)
{
DependencyResolutionLocatorKey result = new DependencyResolutionLocatorKey(t, id);
// 是否有自己的具体创建方针
ITypeMappingPolicy policy = context.Policies.Get<ITypeMappingPolicy>(t, id);
// 有自己的创建方针,则执行
if (policy != null)
{
result = policy.Map(result);
TraceBuildUp(context, t, id, Properties.Resources.TypeMapped, result.Type, result.ID ?? "(null)");
Guard.TypeIsAssignableFromType(t, result.Type, t);
}
// 执行创建动作
return base.BuildUp(context, result.Type, existing, result.ID);
}
}
有了抽象策略角色(BuilderStrategy),也有了具体策略角色(TypeMappingStrategy、……),还缺少一个环境角色。所以我们需要构造一个环境角色。
在办理身份证的过程中,我指定了一个执行方案,这个方案执行了策略,它就充当了整个环节中的环境角色。
在ObjectBuilder的环境中,IBuilder定义了ObjectBuilder所需要的环境角色的接口规范:
BuilderBase定义了一个抽象的基类,Builder定义了一个真正的环境对象。默认了一系列的策略调用顺序:
{
// 类型映射策略
Strategies.AddNew<TypeMappingStrategy>(BuilderStage.PreCreation);
// 单例策略
Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation);
// 构造器反射策略
Strategies.AddNew<ConstructorReflectionStrategy>(BuilderStage.PreCreation);
// 属性反射策略
Strategies.AddNew<PropertyReflectionStrategy>(BuilderStage.PreCreation);
// 方法反射策略
Strategies.AddNew<MethodReflectionStrategy>(BuilderStage.PreCreation);
// 创建策略
Strategies.AddNew<CreationStrategy>(BuilderStage.Creation);
// 属性设置器策略
Strategies.AddNew<PropertySetterStrategy>(BuilderStage.Initialization);
// 方法执行策略
Strategies.AddNew<MethodExecutionStrategy>(BuilderStage.Initialization);
// 创建器感知策略
Strategies.AddNew<BuilderAwareStrategy>(BuilderStage.PostInitialization);
Policies.SetDefault<ICreationPolicy>( new DefaultCreationPolicy());
if (configurator != null)
configurator.ApplyConfiguration( this);
}
当然这些是ObjectBuilder默认的一个策略过程,我们仍然可以做自己的扩展,比如DataAccess Block里面的:(关于ObjectBuilder的扩展以后再细说)
{
builder = new BuilderBase<BuilderStage>();
builder.Strategies.AddNew<ConfigurationNameMappingStrategy>(BuilderStage.PreCreation);
builder.Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation);
builder.Strategies.AddNew<ConfiguredObjectStrategy>(BuilderStage.PreCreation);
builder.Strategies.AddNew<InstrumentationStrategy>(BuilderStage.PostInitialization);
}
结束语:
综上所述,ObjectBuilder的创建策略(BuilderStrategy)已经具有了策略模式的3个基本备对象
- 环境角色
- 抽象策略角色
- 具体策略角色
我们温习一下策略模式的定义:
“策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。”
ObjectBuilder的创建策略(BuilderStrategy),但是他们却不是用来互换的,而是互相补充互相完善了,所以应该是一系列的连贯动作,看起来好像并不完全符合策略模式的定义。
毛主席很早就教导过我们:团结就是力量。所以孤立存在的一个创建策略(BuilderStrategy)并不一定能解决问题,ObjectBuilder还需要用责任链模式把这一系列的创建策略组织起来才能完成一个对象的创建过程
to be continued……
―――――――――――――――――――――――――――――――――――――――――――――
参考资料:
吕震宇老师之设计模式(22)-Strategy Pattern
niwalker的专栏之ObjectBuilder技术内幕
分类: 1.首页原创精华.NET区123,IoC / DI,浪子学编程
本文转自浪子博客园博客,原文链接:http://www.cnblogs.com/walkingboy/archive/2006/04/21/380938.html,如需转载请自行联系原作者