文章出處

索引

意圖

將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

結構

參與者

Builder

  • 為創建一個 Product 對象的各個部件指定抽象接口。

ConcreteBuilder

  • 實現 Builder 的接口以構造和裝配該產品的各個部件。
  • 定義并明確它所創建的表示。
  • 提供一個檢索產品的接口。

Director

  • 構造一個使用 Builder 接口的對象。

Product

  • 表示被構造的復雜對象。ConcreteBuilder 創建該產品的內部表示并定義它的裝配過程。
  • 包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。

適用性

在以下情況下可以使用 Builder 模式:

  • 當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時。
  • 當構造過程必須允許被構造的對象有不同的表示時。

效果

  • 它使你可以改變一個產品的內部表示。在改變該產品的內部表示時所要做的只是定義一個新的 ConcreteBuilder。
  • 它將構造代碼和表示代碼分開,提高了對象的模塊性。客戶不需要知道定義產品內部結構的類的所有信息。
  • 它使你可以對構造過程進行更精細的控制。對象是在 Director 的控制下一步一步構造的,僅當產品構造完成時 Director 才從 Builder 中取回它。

相關模式

  • Abstract Factory 和 Builder 相似,因為它也可以創建復雜對象。區別是 Builder 著重于一步步構造一個復雜對象。而 Abstract Factory 著重于多個系列的產品對象(或簡單或復雜)。Builder 是在最后一步返回產品,Abstract Factory 是立即返回。
  • Composite 通常是用 Builder 生成的。

實現

實現方式(一):Builder 為每個構件定義一個操作。

通常有一個抽象的 Builder 類為 Director 可能要求創建的每一個 "構件" 定義一個操作。這些操作默認情況下什么都不做。一個 ConcreteBuilder 類對它感興趣的 "構件" 對應的操作進行重定義。

 1 namespace BuilderPattern.Implementation1
 2 {
 3   public class ComplexProduct
 4   {
 5     public string ValueDependOnWeather { get; set; }
 6     public string ValueDependOnFortune { get; set; }
 7   }
 8 
 9   public abstract class AbstractComplexProductBuilder
10   {
11     protected ComplexProduct _complexProduct;
12 
13     public void BeginBuild(ComplexProduct existingComplexProduct = null)
14     {
15       if (existingComplexProduct == null)
16         _complexProduct = new ComplexProduct();
17       else
18         _complexProduct = existingComplexProduct;
19     }
20 
21     public virtual void BuildValueDependOnWeatherPart(string weather)
22     {
23       // could do nothing by default
24       _complexProduct.ValueDependOnWeather = weather;
25     }
26 
27     public virtual void BuildValueDependOnFortunePart(string luck)
28     {
29       // could do nothing by default
30       _complexProduct.ValueDependOnFortune = luck;
31     }
32 
33     public ComplexProduct EndBuild()
34     {
35       return this._complexProduct;
36     }
37   }
38 
39   public class ConcreteProductBuilderA : AbstractComplexProductBuilder
40   {
41     private string _dayOfWeek;
42     private int _luckyNumber;
43 
44     public ConcreteProductBuilderA(string dayOfWeek, int luckyNumber)
45     {
46       _dayOfWeek = dayOfWeek;
47       _luckyNumber = luckyNumber;
48     }
49 
50     public override void BuildValueDependOnWeatherPart(string weather)
51     {
52       // something customized
53       _complexProduct.ValueDependOnWeather = _dayOfWeek + " is " + weather;
54     }
55 
56     public override void BuildValueDependOnFortunePart(string luck)
57     {
58       // something customized
59       if (_luckyNumber == 8)
60         _complexProduct.ValueDependOnFortune = "Supper" + luck;
61       else
62         _complexProduct.ValueDependOnFortune = "Just so so" + luck;
63     }
64   }
65 
66   public class GoodWeatherAndGoodLuckDirector
67   {
68     public void ConstructWithGoodWeatherAndGoodLuck(AbstractComplexProductBuilder builder)
69     {
70       builder.BuildValueDependOnWeatherPart(@"PM2.5 < 50");
71       builder.BuildValueDependOnFortunePart(@"Good Luck");
72     }
73 
74     public void ConstructWithBadWeatherAndBadLuck(AbstractComplexProductBuilder builder)
75     {
76       builder.BuildValueDependOnWeatherPart(@"PM2.5 > 500");
77       builder.BuildValueDependOnFortunePart(@"Bad Luck");
78     }
79   }
80 
81   public class Client
82   {
83     public void TestCase1()
84     {
85       AbstractComplexProductBuilder builder = new ConcreteProductBuilderA("Sunday", 9);
86       GoodWeatherAndGoodLuckDirector director = new GoodWeatherAndGoodLuckDirector();
87 
88       builder.BeginBuild();
89       director.ConstructWithGoodWeatherAndGoodLuck(builder);
90       ComplexProduct productWithGoodLuck = builder.EndBuild();
91 
92       builder.BeginBuild();
93       director.ConstructWithBadWeatherAndBadLuck(builder);
94       ComplexProduct productWithBadLuck = builder.EndBuild();
95     }
96   }
97 }

實現方式(二):Builder 將構件返回給 Director,Director 將構件傳遞給 Builder 中的下一個步驟。

Builder 逐步的構造產品,所以其接口必須足夠的普遍。如果構造過程中需要訪問前面已經構造了的產品構件,則 Builder 將構件返回給 Director,由 Director 將構件傳遞給 Builder 中的下一個步驟。

  1 namespace BuilderPattern.Implementation2
  2 {
  3   public class ComplexProduct
  4   {
  5     public string ValueDependOnWeather { get; set; }
  6     public string ValueDependOnFortune { get; set; }
  7   }
  8 
  9   public abstract class AbstractComplexProductBuilder
 10   {
 11     protected ComplexProduct _complexProduct;
 12 
 13     public void BeginBuild(ComplexProduct existingComplexProduct = null)
 14     {
 15       if (existingComplexProduct == null)
 16         _complexProduct = new ComplexProduct();
 17       else
 18         _complexProduct = existingComplexProduct;
 19     }
 20 
 21     public virtual string BuildValueDependOnWeatherPart(string weather)
 22     {
 23       // could do nothing by default
 24       _complexProduct.ValueDependOnWeather = weather;
 25       return _complexProduct.ValueDependOnWeather;
 26     }
 27 
 28     public virtual string BuildValueDependOnFortunePart(string luck, string combinedWithWeather)
 29     {
 30       // could do nothing by default
 31       _complexProduct.ValueDependOnFortune = luck + combinedWithWeather;
 32       return _complexProduct.ValueDependOnFortune;
 33     }
 34 
 35     public ComplexProduct EndBuild()
 36     {
 37       return this._complexProduct;
 38     }
 39   }
 40 
 41   public class ConcreteProductBuilderA : AbstractComplexProductBuilder
 42   {
 43     private string _dayOfWeek;
 44     private int _luckyNumber;
 45 
 46     public ConcreteProductBuilderA(string dayOfWeek, int luckyNumber)
 47     {
 48       _dayOfWeek = dayOfWeek;
 49       _luckyNumber = luckyNumber;
 50     }
 51 
 52     public override string BuildValueDependOnWeatherPart(string weather)
 53     {
 54       // something customized
 55       _complexProduct.ValueDependOnWeather = _dayOfWeek + " is " + weather;
 56       return _complexProduct.ValueDependOnWeather;
 57     }
 58 
 59     public override string BuildValueDependOnFortunePart(string luck, string combinedWithWeather)
 60     {
 61       // something customized
 62       if (_luckyNumber == 8)
 63         _complexProduct.ValueDependOnFortune = "Supper" + luck + combinedWithWeather;
 64       else
 65         _complexProduct.ValueDependOnFortune = "Just so so" + luck + combinedWithWeather;
 66       return _complexProduct.ValueDependOnFortune;
 67     }
 68   }
 69 
 70   public class GoodWeatherAndGoodLuckDirector
 71   {
 72     public void ConstructWithGoodWeatherAndGoodLuck(AbstractComplexProductBuilder builder)
 73     {
 74       string weather = builder.BuildValueDependOnWeatherPart(@"PM2.5 < 50");
 75       builder.BuildValueDependOnFortunePart(@"Good Luck", weather);
 76     }
 77 
 78     public void ConstructWithBadWeatherAndBadLuck(AbstractComplexProductBuilder builder)
 79     {
 80       string weather = builder.BuildValueDependOnWeatherPart(@"PM2.5 > 500");
 81       builder.BuildValueDependOnFortunePart(@"Bad Luck", weather);
 82     }
 83   }
 84 
 85   public class Client
 86   {
 87     public void TestCase2()
 88     {
 89       AbstractComplexProductBuilder builder = new ConcreteProductBuilderA("Sunday", 9);
 90       GoodWeatherAndGoodLuckDirector director = new GoodWeatherAndGoodLuckDirector();
 91 
 92       builder.BeginBuild();
 93       director.ConstructWithGoodWeatherAndGoodLuck(builder);
 94       ComplexProduct productWithGoodLuck = builder.EndBuild();
 95 
 96       builder.BeginBuild();
 97       director.ConstructWithBadWeatherAndBadLuck(builder);
 98       ComplexProduct productWithBadLuck = builder.EndBuild();
 99     }
100   }
101 }

設計模式之美》為 Dennis Gao 發布于博客園的系列文章,任何未經作者本人同意的人為或爬蟲轉載均為耍流氓。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()