zoukankan      html  css  js  c++  java
  • 一天一个设计模式——Builder建造者模式

    一、模式说明

      在现实世界中,当我们要构造一个大型工程时(建一个大楼),通常的做法是先建造工程的每个独立部分,然后再逐步构造完成(先打地基,再搭框架,最后逐层累造)。在程序设计领域,构造一个复杂的类时(或一些具有类似结构的复杂类时),也可以采用类似的思想:如果要创建一个用于构造文档的类(或者是word,或者是html),虽然具体的文档有不同的结构,但是构造这些对象有相同的套路:创建标题,创建内容,创建条目,结束文档。Builder建造者模式就是用来构造复杂的类的。

    二、模式类图

    三、模式时序图

    四、模式中的角色

    • Builder建造者:负责定义用于生成实例的接口(API),准备了生成实例的方法。
    • ConcreteBuilder具体的建造者:负责实现Builder角色的接口类(API),这里定义了生成实例时调用的方法,并且定义了获取最终生成结果的方法。
    • Director监工角色:负责使用Builder角色的接口(API)来生成实例。它并不依赖于具体的ConcreteBuilder角色,为了确保无论ConcreteBuilder如何被定义,Director角色都能正常工作,它只调用在Builder角色中被定义的方法。
    • Client使用者角色:使用Builder模式(Main 方法类)

    五、代码示例

    1、Builder建造者类:

    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

    抽象类,它定义了生成实例的接口。

    2、Director监工:

    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)

    3、接下来是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("
    ");
        }
        public void makeString(String str){
            buffer.append("[" + str + "
    ");
            buffer.append("
    ");
        }
        public void makeItems(String[] items){
            for (String item: items
                 ) {
                buffer.append("   ." + item + "
    ");
            }
            buffer.append("
    ");
        }
        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

    4、运行结果:

    给程序传递参数:

    运行结果:

    传递html时的运行结果:

    html显示效果:

    六、相关的设计模式

    • Template Method模板方法模式:这个比较明显了:在一个类中定义方法和方法调用顺序,子类则实现方法,都是父类控制子类。
    • Composite组合模式:有些时候,可以用Builder模式生成的实例用于构成Composite组合模式。
    • Abstract Factory抽象工厂模式:都用于生成复杂的实例。
    • Facade模式:外观模式:通过组合内部模块,向外部提供可以简单调用的API,隐藏子系统的复杂性。

    七、拓展思路

    • 【谁知道什么】在编程中,谁知道什么很重要,上面的程序Main客户端类并不知道Builder类,它只调用了Director监工类的construct建造方法,Director类就可以开始工作并完成文档创建。另一方面,Director知道Builder,它调用Builder的方法来构造文档,但是Director并不知道具体的Builder是谁(是哪个子类,plainText还是html?),也是正因为Director类不知道Builder是谁,才使得Builder可以被替换成不同的Builder子类。正因为不知道才可以替换。
    • 【设计阶段能决定什么,不能决定什么】Builder类中需要声明生成文档需要实现的所有方法,Director类中使用的方法都是Builder提供的,因此Builder类中应当定义哪些方法,这个问题很重要,需要慎重设计以应对程序后期变化。
  • 相关阅读:
    fastjson转换包含date类型属性的对象时报错com.alibaba.fastjson.JSONException: For input string: "13:02:19"
    HTTP Status 500
    org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
    myeclipse 报错:Set project compiler compliance settings to '1.5'
    Myeclipse安装svn插件
    junit单元测试报错Failed to load ApplicationContext,但是项目发布到tomcat浏览器访问没问题
    使用mybatis时,sql查出来的结果映射不进逆向工程生成的该模型
    整合mybatis时报错:Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/tx]
    TinkerPop中的遍历:图的遍历步骤(3/3)
    TinkerPop中的遍历:图的遍历步骤(2/3)
  • 原文地址:https://www.cnblogs.com/zheng-hong-bo/p/11100397.html
Copyright © 2011-2022 走看看