JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » GoF  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 Design Patterns 入門 - 建築者(Builder) [精華]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2003-12-08 17:00 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
此文件已有新版
http://openhome.cc/Gossip/DesignPattern/

考慮今天您要建立一個車庫,您已經構想好一個基本的車庫藍圖,這個車庫的功能很簡單,有一個屋頂、四面牆,其中一面牆設有一個車子進出的門,因為預算的關係,這個車庫要用哪些材質來建立您還沒有決定,您找了兩個建車庫的人,其中一個可以幫您建立一個實用的車庫,但索價較高,另一個的索價較低,但所用的材質都是木頭而已。

無論如何您最終的選擇是什麼,建車庫的人只要按照您的藍圖來建車庫,功能上都是可以達到您的要求的,您這時所扮演的是指導者(Director)的角色,而建車庫的人是建築者(Builder),假設以上所述是一個模擬遊戲中的情節,我們可以使用建築者模式來構造我們的程式結構,如下圖所示:


在這邊我們所觀注的是建立屋頂、牆、門這些元件(component)的操作方法,對身為設計者的您而言,這三個方法必須合乎您的設計藍圖,我們簡單的將這個結構實現如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class Designer {
        private String[] blueprint = {"牆", "屋頂", "門"};
 
  public void buildGarage(GarageBuilder builder) {
            for(int i = 0; i < blueprint.length; i++) {
                if(blueprint[i].equals("牆"))
                    builder.makeWall();
                else if(blueprint[i].equals("屋頂"))
                    builder.makeRoof();
                else if(blueprint[i].equals("門"))
                    builder.makeDoor();
            }
  }
}
 
public abstract class GarageBuilder {
  private  Designer builder;
  public abstract void makeWall();
  public abstract void makeDoor();
  public abstract void makeRoof();
  public abstract void printGarage();
}
 
public class CheapBuilder extends GarageBuilder {
        private String _cheapGarage = "便宜車庫 = ";
 
        public void makeWall() {
            _cheapGarage = _cheapGarage + "四個木牆 ";
        }
 
        public void makeRoof() {
            _cheapGarage = _cheapGarage + "一個木屋頂 ";
        }
 
        public void makeDoor() {
            _cheapGarage = _cheapGarage + "一個木門 ";
        }
 
            // 這只是顯示成品而已
        public void printGarage() {
            System.out.println("成品: " + _cheapGarage);
        }
}
 
public class PracticalBuilder extends GarageBuilder {
        private String _practicalGarage = "實用車庫 = ";
 
        public void makeWall() {
            _practicalGarage = _practicalGarage + "四個水泥牆 ";
        }
 
        public void makeRoof() {
            _practicalGarage = _practicalGarage + "一個鐵屋頂 ";
        }
 
        public void makeDoor() {
            _practicalGarage = _practicalGarage + "一個電動門 ";
        }
 
            // 這只是顯示成品而已
      public void printGarage() {
            System.out.println("成品: " + _practicalGarage);
      }
}
 
public class Main {
        public static void main(String[] args) {
            Designer you = new Designer();
            GarageBuilder builder = new CheapBuilder();
        
            you.buildGarage(builder);
            // 這只是顯示成品而已
            builder.printGarage();
        }
}


在我們的結構圖中,有生成實質的車庫產品,而在上面的簡單實現中,只是用字串簡單的實現而已,當然,如果您的產品提供操作,您也可以設計一個抽象介面,並透過抽象介面來操作實現的子類別,您可以使用之前談過的相關模式,或是其它模式來定義與實作您的產品,這就看您的程式要用這個產品作些什麼了。

我們將建築者模式的結構畫出如下:


在Gof(Gang of four)中有給出了一個不錯的例子,以設計文件剖析器為例,該剖析器可以將文件轉換為其它的格式,以DOC文件剖析器為例好了,假設我們希望析剖器可以將DOC文件轉換為RTF或是PDF文件,我們可以如下設計結構:


簡單來說,建築者模式適用的場合,在於使得相同的建築過程可以建立不同的實例,這是其之所以命為Builder的原因。


caterpillar edited on 2013-04-07 15:48
reply to postreply to post
良葛格學習筆記
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:caterpillar]
robinjam





發文: 34
積分: 0
於 2004-02-13 00:19 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
請問一下,你說的"在這邊getPracticalGarage()或getCheapGarage()這兩個方法要在子類別中定義,或是在抽象父類別中以抽象方法定義是取決於您的程式",假如我要建造一個塑膠做的車庫...那是不是要在子類別補加
getPlasticsGarage()的函示...這樣好像很麻煩..Designer的程式碼也要變動
以小弟的感覺..我覺得應該不需加getPracticalGarage()或是getCheapGarage()...而是統一在父類別加上getGarage()或是放在Designer...負責建造車庫的邏輯
1
2
3
4
5
6
public void getGarage()
{
  makeWall();
  makeDoor();
  makeRoof();
}


這樣會不會比較好用...不會的部分集合在一起...會變動的部分封裝起來
比較符合DB的精神


morchory edited on 2004-08-26 15:11
reply to postreply to post
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:caterpillar]
todoelie





發文: 20
積分: 0
於 2004-06-23 17:40 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
如果要做一個 塑膠做的車庫 ,只要再另外
建立一個 PlasticBuilder 的子類別,我覺得並不會麻煩…
而且 Designer 的程式碼也不用變動

另外如果在父類別加上一個 getGarage(),我也是覺得這樣比
較好,因為這個方法是所有子類別都會有的,所以
子類別只需要依自己的需求去實作他就可以了…

而這個 getGarage()應該是不能放在 Designer 的吧…
這樣整個結構就亂掉了的感覺… ^^||


reply to postreply to post
若po的文章有觀念有錯,請大家指正…(y)
謝謝…(b)
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:caterpillar]
todoelie





發文: 20
積分: 0
於 2004-06-25 17:33 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
我稍為補充一下我上一篇的回應…如果觀念有錯請馬上糾正…^^
一般在使用 Builder Pattern 的時候,Client端(使用者) 直接會先選擇需要那一個 Builder ,然後建構一個Dircector (Designer) 請它幫忙指導Builder去建造出一個產品之後,傳回給使用端.... (請參考上面 Main Class 的 Code)

上面的例子中,產品之間都有共通點…但有時候,產品之間的差異性很大,這時候就需要 <標示介面> 取代其 <抽像類別> or <介面> .
PS: 標示介面 就是沒有內容、空的介面

另外差異性大的時候(一顆球跟一本書),Builder 的每一個子類別都需要對應到不同的產品去做建構的動作、方法,而在他們的父類別 Builder 這個抽象類別中每個方法可以宣告成 builderPart1() ,builderPart2() .....端看需要幾個 builderPart ...,而繼承他的子類別看自己的需求去實作 (有先後順序) ,用不到這麼多的就實作內容就留空白。

而Director 根據 Client 端傳進來的 builder,來做指導(操作) Builder 建構(有先後順序),完成後傳回 或其它...

所以 robinjam 兄所說的
1
2
3
4
5
6
public void getGarage()
{  
   makeWall(); 
   makeDoor();  
   makeRoof();
}

應該是不能成立的,因為這些 makeWall()....等方法,應該要在 Designer 內呼叫,由Director (Designer) 去指導 Builder 那個該先做,那個要後做。

在上面的例子中,雖然沒有先後順序,makeWall()...等方法,應該算在 Director (Designer) 的責任範圍之內。 除非因為需求而只有一個 具體的 Builder 同時省略 了 抽象類別 與 Driector 的角色。

如果我說的地方有那個地方不好,會是錯的,請馬上糾正,這樣才不會誤導觀看文章的人… ^^


todoelie edited on 2004-06-25 17:39
reply to postreply to post
若po的文章有觀念有錯,請大家指正…(y)
謝謝…(b)
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:caterpillar]
ajyi





發文: 55
積分: 1
於 2008-07-16 16:54 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
最近在爬各位大大對於Design Patterns的文章,對於Builder和Abstract Factory的差異有點疑問,不知道這樣說對不對?
Builder最重要的精神在於Director,將處理復雜物件的程序(藍圖)在Director中完成,而Director與Builder及Product的關係其實就是一種Abstract Factory

繼續爬文中...


ajyi edited on 2008-07-16 16:57
reply to postreply to post
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:ajyi]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2008-07-16 17:46 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ajyi wrote:
最近在爬各位大大對於Design Patterns的文章,對於Builder和Abstract Factory的差異有點疑問,不知道這樣說對不對?
Builder最重要的精神在於Director,將處理復雜物件的程序(藍圖)在Director中完成,而Director與Builder及Product的關係其實就是一種Abstract Factory

繼續爬文中...


比較大的差異應該是
Abstract Factory可以給任意的東西呼叫並直接回傳成品,但是builder期待會被director呼叫一步一步產生最後的成品!?

而你說的關係 "Director與Builder及Product的關係其實就是一種Abstract Factory"好像不太正確!?
使用Abstract Factory時呼叫者不會知道他會回傳哪種product.
但是使用director時, 必須告知director他現在該利用哪種builder產生product吧!?

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:Design Patterns 入門 - 建築者(Builder) [Re:koji]
ajyi





發文: 55
積分: 1
於 2008-07-17 10:08 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
感謝koji大願意指導一下我這初學者
我的對應方式是這樣的
Abstract Factory的Client對應Director
Abstract Factory的IFactory對應IBuilder
Abstract Factory的IProduct對應IProduct
其實兩者都對Factory(Builder)與Product抽象
而希望他們的Client(Director)要依賴於抽象而不是實體Class

我的意思是說在設計Builder Design Pattern有使用到Abstract Factory Design Pattern
而這兩種Pattern對Client來說當然是不一樣的
我想大大所提的
koji wrote:
而你說的關係 "Director與Builder及Product的關係其實就是一種Abstract Factory"好像不太正確!?
使用Abstract Factory時呼叫者不會知道他會回傳哪種product.
但是使用director時, 必須告知director他現在該利用哪種builder產生product吧!?

我想是指對這兩種Pattern的Client端來說的差異點吧?
不知道有沒有搞錯Blush

說一下我閱讀Builder的經驗,希望對其他人在閱讀時有幫助
在剛開始看Builder Pattern時
會很自然的將焦點放在IBuilder
因此也會覺得很疑惑
除了Director是一種特殊的Client外
看不出Builder與Abstract Factory太大的不同
後來看到良葛格大的網頁中最後提到的『建築者模式適用的場合,在於使得您可以依賴抽象的建築藍圖,而實際建造時可以使用不同的實例,這是其之所以命為Builder的原因。』
才對Builder有所領悟


reply to postreply to post
» JWorld@TW »  Software Design » GoF

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8