1. 程式人生 > >初步認知:建造者模式

初步認知:建造者模式

在講述這個模式之前,我們先看一個案例:建造小人(只需要建造的小人有頭、身子、四肢即可)

public class DrawPeople extends JFrame {
    //DrawSee構造方法
    public DrawPeople() {
        setBounds(0, 0, 500, 500);//窗體起始位置
        setVisible(true);//窗體是否可見
        setLayout(null); //窗體佈局  
        setResizable(false);//窗體是否可進行拖動設定大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        
        
try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } // 獲取專門用於在視窗介面上繪圖的物件 Graphics jg = this.getGraphics(); // 繪製區域 paintComponents(jg); } //畫一個人 public void paintComponents(Graphics g) {
try { g.drawArc(150, 50, 30, 30, 0, 360);//畫頭 g.drawArc(145, 80, 40, 50, 0, 360);//畫身子 g.drawLine(150, 80, 130, 130); g.drawLine(180, 80, 200, 130); g.drawLine(160, 130, 145, 180); g.drawLine(170, 130, 185, 180); } catch (Exception e) { e.printStackTrace(); } } } 測試方法
public class Test { public static void main(String[] args) { new DrawPeople(); } }

繪製結果如下圖所示

那我現在需要繪製一個比較瘦的人,怎麼辦?

正常程式設計師都會想:這還不簡單,把這個類複製一份,把繪製引數改下不就行了。

那萬一複製的時候少複製了一行,讓小人缺胳膊少腿怎麼辦?

這對一個人來說可是巨大的損失,誰都不想讓身體殘缺不全。這個問題怎麼解決呢?

下面介紹建造者模式:http://www.runoob.com/design-pattern/builder-pattern.html

將一個複雜物件的構建與他的表示分離,使得同樣的構建過程可以建立不同的表示。

那怎麼用建造者模式呢?

以畫小人為例,我們需要畫頭、身體、左手、右手、左腳、右腳,所以我們先定義一個抽象的建造人的類,把這個過程穩定住,不讓任何人遺忘當中的任何一步。

public interface PersonBuilder {
    public abstract void buildHead();
    public abstract void buildBody();
    public abstract void buildArmLeft();
    public abstract void buildArmRight();
    public abstract void buildLegLeft();
    public abstract void buildLegRight();
}

然後我們需要建造一個胖的人,就讓這個胖子類取繼承這個抽象類,那就必須去重寫這些抽象方法了,否則編譯器也不讓你通過。

public class PersonFatBuilder extends JFrame implements PersonBuilder{

    private Graphics  g;

    public PersonFatBuilder() {
        setBounds(0, 0, 500, 500);//窗體起始位置
        setVisible(true);//窗體是否可見
        setLayout(null); //窗體佈局  
        setResizable(false);//窗體是否可進行拖動設定大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        
        try {
            Thread.sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
        }        
        // 獲取專門用於在視窗介面上繪圖的物件
        this.g =  this.getGraphics();
        
        // 繪製遊戲區域
        paintComponents(this.g);
    }

    @Override
    public void buildHead() {
        g.drawArc(150, 50, 30, 30, 0, 360);//畫頭
    }

    @Override
    public void buildBody() {
        g.drawArc(145, 80, 40, 50, 0, 360);//畫身子
    }

    @Override
    public void buildArmLeft() {
        g.drawLine(150, 80, 130, 130);
    }

    @Override
    public void buildArmRight() {
        g.drawLine(180, 80, 200, 130);
    }

    @Override
    public void buildLegLeft() {
        g.drawLine(160, 130, 145, 180);
    }

    @Override
    public void buildLegRight() {
        g.drawLine(170, 130, 185, 180);
    }
}

瘦子類也是用類似的程式碼去實現這個類就可以了。

但現在只是保證胖子類擁有了頭身手腳方法,但依然無法保證這些方法一定會被呼叫,怎麼辦?

我們還缺少建造者模式中一個重要的類,指揮者(Director),用它來控制建造過程,也用它來隔離使用者與建造過程的關聯。

public class PersonDirector {
    private PersonBuilder pb;
    //使用者告訴指揮者,我需要什麼樣的小人
    public PersonDirector(PersonBuilder pb){
        this.pb = pb;
    }
    //根據使用者的選擇建造小人
    public void createPerson(){
        pb.buildHead();
        pb.buildBody();
        pb.buildArmLeft();
        pb.buildArmRight();
        pb.buildLegLeft();
        pb.buildLegRight();
    }
}

測試方法

public class Test {
    public static void main(String[] args) {
        PersonFatBuilder pfb = new PersonFatBuilder();
        PersonDirector pd = new PersonDirector(pfb);
        pd.createPerson();
    }
}

PersonDirector類的目的就是根據使用者的選擇來一步步建造小人,而建造的過程在指揮者這裡完成,使用者就不需要知道了,而且,每個建造過程都是一定要做的,保證了建造流程的正確性,這樣,缺胳膊少腿的情況就不會出現了。

做個比喻:Builder像是圖紙,PersonFatBuilder是具體的施工人員,PersonDirector就是個監工,保證施工過程正確有序。