一天一个设计模式——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类中应当定义哪些方法,这个问题很重要,须要慎重设计以应对程序后期变化。
相关文章
相关标签/搜索