一天一個設計模式——Builder建造者模式

 

1、模式說明html

  在現實世界中,當咱們要構造一個大型工程時(建一個大樓),一般的作法是先建造工程的每一個獨立部分,而後再逐步構造完成(先打地基,再搭框架,最後逐層累造)。在程序設計領域,構造一個複雜的類時(或一些具備相似結構的複雜類時),也能夠採用相似的思想:若是要建立一個用於構造文檔的類(或者是word,或者是html),雖然具體的文檔有不一樣的結構,可是構造這些對象有相同的套路:建立標題,建立內容,建立條目,結束文檔。Builder建造者模式就是用來構造複雜的類的。java

2、模式類圖編程

3、模式時序圖設計模式

4、模式中的角色app

  • Builder建造者:負責定義用於生成實例的接口(API),準備了生成實例的方法。
  • ConcreteBuilder具體的建造者:負責實現Builder角色的接口類(API),這裏定義了生成實例時調用的方法,而且定義了獲取最終生成結果的方法。
  • Director監工角色:負責使用Builder角色的接口(API)來生成實例。它並不依賴於具體的ConcreteBuilder角色,爲了確保不管ConcreteBuilder如何被定義,Director角色都能正常工做,它只調用在Builder角色中被定義的方法。
  • Client使用者角色:使用Builder模式(Main 方法類)

5、代碼示例框架

一、Builder建造者類:ide

package com.designpattern.cn.builderpattern;

public abstract class Builder {
    public abstract void makeTitle(String title);
    public abstract void makeString(String string);
    public abstract void makeItems(String[] items);
    public abstract void close();
}
View Code

抽象類,它定義了生成實例的接口。函數

二、Director監工:ui

package com.designpattern.cn.builderpattern;

public class Director {
    public Builder builder;
    public Director(Builder builder){
        this.builder = builder;
    }

    public void construct(){
        builder.makeTitle("Greeting");
        builder.makeString("A.M. to P.M.");
        builder.makeItems(new String[]{
                "Good morning",
                "Good afternoon"
        });
        builder.makeString("Night");
        builder.makeItems(new String[]{
                "Good night",
                "Bye"
        });
        builder.close();
    }
}
View Code

注意Director的構造函數,它有一個Builder類型參數,但實際上並不能直接傳遞Builder實例(Builder是抽象類,沒法構造實例),而是傳遞一個Builder的子類(TextBuilder或者是HtmlBuilder)this

三、接下來是Builder的兩個子類,它是實例類,能夠建立對象。

package com.designpattern.cn.builderpattern;

public class TextBuilder extends Builder {
    private StringBuffer buffer = new StringBuffer();
    public void makeTitle(String title){
        buffer.append("==================");
        buffer.append("[" + title +"]");
        buffer.append("\n");
    }
    public void makeString(String str){
        buffer.append("[" + str + "\n");
        buffer.append("\n");
    }
    public void makeItems(String[] items){
        for (String item: items
             ) {
            buffer.append("   ." + item + "\n");
        }
        buffer.append("\n");
    }
    public void close(){
        buffer.append("==================");
    }
    public String getResult(){
        return buffer.toString();
    }
}
View Code

 

package com.designpattern.cn.builderpattern;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class HtmlBuilder extends Builder {
    private String filename;
    private PrintWriter writer;
    public void makeTitle(String title){
        filename = title+".html";
        try {
            writer = new PrintWriter(new FileWriter(filename));
        }catch (IOException e){
            e.printStackTrace();
        }
        writer.println("<html><head><title>"+title+"</title></head><body>");
        writer.println("<h1>"+title+"</h1>");
    }
    public void makeString(String str){
        writer.println("<p>" + str + "</p>");
    }
    public void makeItems(String[] items){
        writer.println("<ul>");
        for (String s : items
             ) {
            writer.println("<li>" + s + "</li>");
        }
        writer.println("</ul>");
    }
    public void close(){
        writer.println("</body></html>");
        writer.close();
    }
    public String getResult(){
        return filename;
    }
}
View Code

四、運行結果:

給程序傳遞參數:

運行結果:

傳遞html時的運行結果:

html顯示效果:

6、相關的設計模式

  • Template Method模板方法模式:這個比較明顯了:在一個類中定義方法和方法調用順序,子類則實現方法,都是父類控制子類。
  • Composite組合模式:有些時候,能夠用Builder模式生成的實例用於構成Composite組合模式。
  • Abstract Factory抽象工廠模式:都用於生成複雜的實例。
  • Facade模式:外觀模式:經過組合內部模塊,向外部提供能夠簡單調用的API,隱藏子系統的複雜性。

7、拓展思路

  • 【誰知道什麼】在編程中,誰知道什麼很重要,上面的程序Main客戶端類並不知道Builder類,它只調用了Director監工類的construct建造方法,Director類就能夠開始工做並完成文檔建立。另外一方面,Director知道Builder,它調用Builder的方法來構造文檔,可是Director並不知道具體的Builder是誰(是哪一個子類,plainText仍是html?),也是正由於Director類不知道Builder是誰,才使得Builder能夠被替換成不一樣的Builder子類。正由於不知道才能夠替換。
  • 【設計階段能決定什麼,不能決定什麼】Builder類中須要聲明生成文檔須要實現的全部方法,Director類中使用的方法都是Builder提供的,所以Builder類中應當定義哪些方法,這個問題很重要,須要慎重設計以應對程序後期變化。
相關文章
相關標籤/搜索