今天,我們來講一下建造者模式。 一、案例 我們來用winform畫一個小人,一個頭,一個身體,兩隻手,兩條腿。 我們一般想到的代碼如下: 運行的效果: 嗯,好,下麵,我們再畫一個稍微胖一點的小人。 代碼如下: 運行效果如下 咦,我們好像少花了條腿哦。 哈哈,像這樣粗心的情況我們經常出現 二、演繹 1 ...
今天,我們來講一下建造者模式。
一、案例
我們來用winform畫一個小人,一個頭,一個身體,兩隻手,兩條腿。
我們一般想到的代碼如下:
1 /// <summary> 2 /// 畫小人 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void pictureBox1_Paint(object sender, PaintEventArgs e) 7 { 8 Graphics gThin = e.Graphics; 9 Pen p = new Pen(Color.Black, 2); 10 gThin.DrawEllipse(p, 50, 20, 30, 30); 11 gThin.DrawRectangle(p, 60, 50, 10, 50); 12 gThin.DrawLine(p, 60, 50, 40, 100); 13 gThin.DrawLine(p, 70, 50, 90, 100); 14 gThin.DrawLine(p, 60, 100, 40, 150); 15 gThin.DrawLine(p, 70, 100, 85, 150); 16 }
運行的效果:
嗯,好,下麵,我們再畫一個稍微胖一點的小人。
代碼如下:
1 private void pictureBox2_Paint(object sender, PaintEventArgs e) 2 { 3 Graphics gThin = e.Graphics; 4 Pen p = new Pen(Color.Red, 2); 5 gThin.DrawEllipse(p, 50, 20, 30, 30); 6 gThin.DrawEllipse(p, 45, 50, 40, 50); 7 gThin.DrawLine(p, 50, 50, 30, 100); 8 gThin.DrawLine(p, 80, 50, 100, 100); 9 gThin.DrawLine(p, 60, 100, 45, 150); 10 }
運行效果如下
咦,我們好像少花了條腿哦。
哈哈,像這樣粗心的情況我們經常出現
二、演繹
1、第一步演繹
1 /// <summary> 2 /// 建造瘦小人的類 3 /// </summary> 4 class PersonThinBuilder 5 { 6 private Graphics _g; 7 private Pen _p; 8 9 public PersonThinBuilder(Graphics g, Pen p) 10 { 11 this._g = g; 12 this._p = p; 13 } 14 /// <summary> 15 /// 建造小人 16 /// </summary> 17 public void Build() 18 { 19 _g.DrawEllipse(_p, 50, 20, 30, 30); 20 _g.DrawRectangle(_p, 60, 50, 10, 50); 21 _g.DrawLine(_p, 60, 50, 40, 100); 22 _g.DrawLine(_p, 70, 50, 90, 100); 23 _g.DrawLine(_p, 60, 100, 40, 150); 24 _g.DrawLine(_p, 70, 100, 85, 150); 25 } 26 }
客戶端
1 private void pictureBox1_Paint(object sender, PaintEventArgs e) 2 { 3 Pen p = new Pen(Color.Black); 4 Graphics gThin = e.Graphics; 5 PersonThinBuilder ptb = new PersonThinBuilder(gThin, p); 6 ptb.Build(); 7 }
我們進行了第一步的改革,看了一下代碼,將客戶端的畫小人的過程一直到了一個類中,客戶端只需要調用這個類就可以了,但是,這仍然沒有解決我們上面提到的問題,如果我們要畫一個胖一點的小人,我們還需要建一個類,然後再寫一遍創建過程,很難保證落下什麼東西(比如:少了一隻手也說不定哦)
好,那麼我們到底該如何解決呢?
下麵就是我們將要介紹的 建造者模式。
建造者模式:將一個對象複雜的構建,與它的表示分離,使得同樣的構建,可以創建不同的表示。
如果我們使用了建造者模式,那麼,用戶只需要指定建造的類型就可以得到他們了,而具體的建造的細節和過程就不需要知道了。
那麼,我們畫小人的案例該怎樣使用建造者模式呢?我們一步步來分析。
畫小人,都需要畫,頭、身體、左手、右手、左腿、右腿。
好,下麵呢,我們就先來定義一個抽象的畫小人的類,將這個過程固定住,不讓任何人遺忘當中的任何一步。
1 abstract class PersonBuilder 2 { 3 protected Graphics G; 4 protected Pen P; 5 6 protected PersonBuilder(Graphics g, Pen p) 7 { 8 G = g; 9 P = p; 10 } 11 12 public abstract void BuildHead(); 13 public abstract void BuildBody(); 14 public abstract void BuildArmLeft(); 15 public abstract void BuildArmRight(); 16 public abstract void BuildLegLeft(); 17 public abstract void BuildLegRight(); 18 }
然後,我們需要建造一個瘦一點的小人,我們可以讓瘦一點的小人去繼承這個抽象類。那麼這個類就必須重寫抽象類中的方法了,要不編譯不通過的。所以,畫小人就不會丟三落四了。
1 class PersonThinBuilder : PersonBuilder 2 { 3 public PersonThinBuilder(Graphics g, Pen p) : base(g, p) 4 { 5 } 6 7 public override void BuildHead() 8 { 9 G.DrawEllipse(P, 50, 20, 30, 30); 10 } 11 12 public override void BuildBody() 13 { 14 G.DrawRectangle(P, 60, 50, 10, 50); 15 } 16 17 public override void BuildArmLeft() 18 { 19 G.DrawLine(P, 60, 50, 40, 100); 20 } 21 22 public override void BuildArmRight() 23 { 24 G.DrawLine(P, 70, 50, 90, 100); 25 } 26 27 public override void BuildLegLeft() 28 { 29 G.DrawLine(P, 60, 100, 40, 150); 30 } 31 32 public override void BuildLegRight() 33 { 34 G.DrawLine(P, 70, 100, 85, 150); 35 } 36 }
同理,胖子小人類也用上面的方式,繼承抽象類,代碼差不多,就不在寫了。
這樣就完事了嗎?如果完事了的話,那麼我在客戶端調用的時候,還是需要調用類裡面的方法,萬一哪一個方法沒有調用,也就會出現丟三落四的情況了,這根本沒有解決問題呀。所以,到這裡,我們還沒有完事呢。
建造者模式還有一個非常重要的類,指揮者類。指揮者類是用來控制建造過程的,同時它也是隔離用戶與建造過程的關聯的。
好,下麵我們來寫一個指揮者類。
1 class PersonDirector 2 { 3 private PersonBuilder pb; 4 //用戶告訴指揮者,我需要什麼樣的小人 5 public PersonDirector(PersonBuilder pb) 6 { 7 this.pb = pb; 8 } 9 //根據用戶的選擇建造小人 10 public void CreatePerson() 11 { 12 pb.BuildHead(); 13 pb.BuildBody(); 14 pb.BuildArmLeft(); 15 pb.BuildArmRight(); 16 pb.BuildLegLeft(); 17 pb.BuildLegRight(); 18 } 19 }
這樣,指揮者類寫好了。其實指揮者類就是根據用戶的選擇,來一步一步的建造小人,而建造的過程在指揮者裡面已經完成了,用戶就不需要知道了。
那麼,客戶端就是這樣的了。
1 private void pictureBox1_Paint(object sender, PaintEventArgs e) 2 { 3 //瘦小人 4 PersonBuilder pb = new PersonThinBuilder(e.Graphics, new Pen(Color.Black)); 5 //告訴建造者,我要創建一個瘦小人 6 PersonDirector pd = new PersonDirector(pb); 7 //開始創建 8 pd.CreatePerson(); 9 }
ok,這樣就成功的將我們的案例用建造者模式構建出來了。
好了,建造者模式今天就講到這裡了,下篇博文我們將 觀察者模式
本系列將持續更新,喜歡的小伙伴可以點一下關註和推薦,謝謝大家的支持。