GOF23种设计模式之Builder Pattern

一:什么是建造模式

       建造模式是对象的创建模式【GOF95】。建造模式可以将一个产品的内部表象和产品的生产过程分割开来,从而可以使一个建造过程生成具有不同内部表象的产品对象。

二:引入建造模式

考虑如下问题:我要建造一部设备(Equipment对象),我们希望将这个复杂的对象的构建与其内部表象分离,使得同样的构建过程可以具有不同内部表象的设备。譬如输入设备,输出设备等。不难看出,这种情况下应该使用建造模式。

就Builder模式来说,最重要的当然是Build行为的抽象。以本例而言,要创建一个Equipment对象,需要Build的是Port和Machine对象,所以我们可以定义两个Build方法的抽象。

void BuildPort();

void BuildMachine(string machineName);

按照这样一个原则,我们可以建立如图17-1所示的类图。

图17-1   Builder类的继承体系

实现代码如下:

public abstract class EQPBuilder

{        

     protected Equipment m_equipment;

     protected Machine m_machine;

     public EQPBuilder()

     {

         m_equipment = new Equipment();

     }

     public abstract void BuildPort();

     public virtual void BuildMachine(string name)

     {

         m_machine = new Machine(name);            

         m_equipment.Name = name;

         m_equipment.Machine = m_machine;

     }

     public Equipment GetEQP()

     {

         return m_equipment;

     }

}

public class InputEQPBuilder:EQPBuilder

{        

     public override void BuildPort()

     {

         Port port = new InputPort();

         m_equipment.AddPort(port);

     }

     public override void BuildMachine(string name)

     {

         base.BuildMachine(name);

         m_machine.PortType = "Input";            

     }

}

public class OutputEQPBuilder:EQPBuilder

{        

     public override void BuildPort()

     {

         Port port = new OutputPort();

         m_equipment.AddPort(port);

     }

     public override void BuildMachine(string name)

     {

         base.BuildMachine(name);

         m_machine.PortType = "Output";            

     }

}

public class IOPutEQPBuilder:EQPBuilder

{        

     public override void BuildPort()

     {

         Port inputPort = new InputPort();

         Port outputPort = new OutputPort();

         m_equipment.AddPort(inputPort);

         m_equipment.AddPort(outputPort);

     }

     public override void BuildMachine(string name)

     {

         base.BuildMachine(name);

         m_machine.PortType = "InputOutput";            

     }

}

由于Builder子类对于Port对象的创建完全不同,因 此我们将父类EQPBuilder中的CreatePort方法定义为抽象方法;至于创建Machine对象的CreateMachine方法,则因为具 有一些共同的逻辑,可以在父类中提供实现,所以被定义为虚方法,并将相同的逻辑抽象到父类中。EQPBuilder的子类需要重写父类的 CreateMachine方法,并在调用父类的CreateMachine方法后,根据创建的Port对象的不同,分别设置Machine对象的 PortType值。

此外,在抽象类EQPBuilder中,定义了GetEQP方法,用于返回一个Equipment对象,这个对象其实就是EQPBuilder类型对象所创建的产品。由于各个Builder子类返回Equipment对象的实现逻辑完全一样,因而被定义为普通方法。

在 Builder模式的实现中,已经有了Product(产品)角色Equipment类对象,有了Builder(建造者)角色EQPBuilder类对 象,以及它的派生子类。现在还缺少一个Director(指导者)角色,用以引入具体建造者角色,指导完成产品的创建。该角色类似于工厂模式中的工厂对 象。因此,我将其定义为LCDFactory,便于调用者理解其职能。

public static class LCDFactory

{

     public static Equipment CreateEQP(EQPBuilder buider, string name)

     {

         buider.BuildPort();

         buider.BuildMachine(name);

         return buider.GetEQP();

     }

}

由于LCDFactory类的静态方法CreateEQP接受的参数是抽象类EQPBuilder,所以指导者角色与建造者角色之间仅存在弱依赖关系,保证了Builder的扩展不会影响产品的创建,类图如图17-2所示。

图17-2   Builder模式的实现类图

与标准的Builder模式不同,为了调用方便,我将EQPBuilder类型中的GetEQP方法也封装到了LCDFactory类中,因此客户端的调用方式应该如下所示。

class Program

{

     static void Main(string[] args)

     {

         EQPBuilder builder = new InputEQPBuilder();

         Equipment eqp = LCDFactory.CreateEQP(builder, "InputMachine");

         eqp.Run();

         builder = new IOPutEQPBuilder();

         eqp = LCDFactory.CreateEQP(builder, "InputOutputMachine");

         eqp.Run();

         Console.Read();

     }

}

三:建造模式的使用情况

      在以下情况下应该使用建造模式:

Case1:需要生成的产品对象有复杂的内部结构。

Case2:需要生成的产品对象的属性相互依赖。

Case3:在对象的创建过程中使用

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章