GoF说明:
将一个复杂对象的构建流程与他的对象表现分离开来,让相同的构建流程可以产生不同的对象行为表现
模式说明:
当你需要一个从构建到行为都非常复杂的对象的时候,你肯定希望找到一个点,用这个点将这个对象的构建和行为区分开。大家可能第一就想到了工厂模式,是的,建造者主要服务于构建复杂的对象,而这个构建行为,通常是在工厂模式下完成的。有所不同的是:通过建造者模式我们可以让不同的角色构建更加灵活多变。
案例说明:构建一个复杂的游戏角色
1.功能需求:构建一个游戏角色,这个游戏角色包含属性、武器、以及所需的游戏物体。并将其加入到统一的角色管理系统中去统一调度。
2.若不使用建造者模式代码分析:
public class Hero{
private Attr mAttr ;
private Weapon mWeapon ;
private string mPrefabName ;
protected void setAttr(Attr attr){
mAttr = attr ;
//TODO Soemthing left
}
protected void setWeapon(Weapon weapon){
mWeapon = weapon;
//TODO Something left
}
protected void createGameObject(string prefabName){
//create gameObject by prefabName
//TODO Soemthing left
}
public void heroAction(){
//处理复杂的人物逻辑
}
}
这样咋一看并没有什么问题,我们甚至可以将Hero做成一个抽象类并实现一个带Attr、Weapon、PrefabName参数的构造函数,如下:
public abstract class IHero{
private Attr mAttr ;
private Weapon mWeapon ;
private string mPrefabName ;
public Hero(Attr attr , Weapon weapon , string prefabName ){
setAttr(attr);
setWeapon(weapon);
createGameObject(prefabName);
}
}
这样做同样可以精简子类实现以及良好的扩展性,但是依旧还是有问题:当构建流程很复杂时,代码量也会及其的多且杂。但是理论上来说,构建角色和角色行为又明显的属于两个不同的领域,当构建或者行为其中一个部分有bug的时候,我们不得不调试整套代码,这对于我们的项目构建是不利的。尤其当构建流程发生改变的时候,我们不得不在一堆及其复杂的代码种进行修改,甚至是修改所有实现的子类。这是相当不必要的。
3.建造者模式:建造者模式就是致力于将对象的构建流程抽象出来,并且提供一套灵活的构建步骤供不同子类实现或修改
4.建造者模式代码分析:建造者模式有两个重要的类
Builder:包含了对象构建的所有步骤
Director:指导Builder的构建流程
这样我们只要持有一个指导者以及一个构建对象,就可以完成一个对象的构建
5.重要代码:
抽象Builder
public abstract class IHeroBuilder {
private Attr mAttr ;
private Weapon mWeapon ;
private string mPrefabName ;
private IHero mHero;
public IHeroBuilder(Attr attr , Weapon weapon , string prefabName ){
this.mAttr = attr ;
this.mWeapon = weapon;
this.mprefabName = prefabName ;
}
protected abstract void DealAttr();
protected abstract void DealWeapon();
protected abstract void DealPrefab();
public IHero getResut() { return mHero;}
}
指导类Director:
public class HeroBuidlerDirector{
private IHeroBuilder mHeroBuidler;
public HeroBuidlerDirector(IHeroBuilder heroBuilder){
mHeroBuidler = heroBuilder;
}
//构建英雄
public IHero construct(){
mHeroBuidler.DealAttr();
mHeroBuidler.DealPrefab();
mHeroBuidler.DealWeapon();
return mHeroBuidler.getResut();
}
}
使用代码,假设HeroBuilder_A继承了IHeroBuilder,并重写了其中的流程。
public class HeroBuilderTest{
public IHero BuilderHero(){
HeroBuilder_A builder = new HeroBuilder_A(new Attr(),new Weapon,'Hero_A_name');
return builder.construct();
}
}
这样我们就把复杂的构建流程抽象出来,供给不同需求的子类去分别实现,但是又能完整的契合进游戏流程。是不是很方便。如果构建的流程有变化我们直接修改Director类就可以了。至于不同的子类差异,也可以在不同的实现Builder中做处反应。如果熟悉模版方法模式的同学,一定会发现两者有着相似的联系,同样是抽象流程,实现细节。有所不同的是建造者模式需要通过一个指导类Dicrtor去完成,相对于模版方法而言,流程的顺序会更加的灵活。