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:在對象的創建過程中使用

 

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