GoF说明:
在一个操作方法中定义算法的流程,其中某些步骤由子类完成。模版方法模式让子类在不变更算法流程的情况下,能够自定义某些步骤的细节。
模式说明:
当项目中某个功能的流程是固定的,但是在不同的子类实现中又有区别。我们就可以定义模版方法模式,将功能指向的方法设置为sealed,不可被重写。将每个步骤都定义成一个protected级别,可供子类重写,但是不可被对象持有者调用。这样子类就可以自定义每个步骤的细节,以此满足不同的功能需求。
案例说明:生成游戏物体
1.需求分析:功能使用者只需要调用Born方法,Born有三个流程,BeforeBorn出生前准备数据,Borning出生,为了让读者熟悉更灵活的编程方式,这里假设Borning方法只由一个不同的参数决定,得到这个参数之后其他的操作流程是一致的,所以笔者这里在IGameObject抽象类中实现了一个DoBorning的方法供Borning调用。最后一个是AfterBorn,处理出生后的事件和数据
2.流程图分析:
这种方法十分的简洁,不同行为的子类,只需要重写这个功能流水线上不同步骤的细节。而对于对象持有者而言,仅仅需要调用同步出来的Born方法就可以了。
3.代码实现:
IGameObject 接口
public abstract class IGameObject{
public sealed void Born(){
BeforeBorn();
Borning();
AfterBorn();
}
//这里要注意一下virtual 与 abstract 的区别
//我们设定并不是所有的游戏物体在生成的时候都要处理生成前和生成后的数据
//比如一些静态的、没有任何功能的装饰物
//Borning是每个物体都必须重写的,所以声明为abstract
protected virtual void BeforeBorn(){ }
protected abstract void Borning();
protected virtual void AfterBorn(){ }
protected sealed void DoBoring(int id ){
//TODO
}
}
IGameObject_A 游戏物体实现,这个物体生成前要准备数据,但是生成后没有处理需求,所以我们重写BeforeBorn以及Borning即可
public class IGameObject_A : IGameObject {
private int mId = 1 ;
protected override void BeforeBorn(){
//TODO
}
protected override void Borning(){
DoBoring(this.mId);
}
}
这种模式设计可以让外界使用的接口更加的清晰简洁,外界的对象持有者仅需要调用born方法。扩展也更加灵活,每个子类都可以实现不同的细节,比如动画、特效、音效等,不同的表现处理。