• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

图解设计模式(7):Builder模式(组装复杂的实例)

设计模式 winrains 1年前 (2019-09-19) 86次浏览

Build模式用于组装具有复杂结构的实例。

1 Build模式中的角色

  • Builder(建造者)

负责定义用于生成实例的接口。Build角色中准确了用于生成实例的方法。在示例中,对应Build类。

  • ConcreteBuilder(具体的建造者)

负责实现Builder角色的接口的类,这里定义了在生成实例时实际被调用的方法。此外,在ConcreteBuilder角色中还定义了获取最终生成结果的方法。在示例中,对应TextBuilder类和HTMLBuilder类。

  • Director(监工)

负责使用Builder角色的接口来生成实例。它并不依赖于ConcreteBuilder角色。为了确保不论ConcreteBuilder角色是如何被定义的,Director角色都能正常工作,它只调用在Builder角色中被定义的方法。在示例中,对应Director类。

  • Client(使用者)

使用Builder模式,在示例中,对应Main类。

2 Builder模式的类图

3 Builder模式的时序图

4 示例程序

4.1 类一览表

名字 说明
Builder 定义了决定文档结构的方法的抽象类
Director 编写一个文档的类
TextBuilder 使用纯文本(普通字符串)编写文档的类
HTMLBuilder 使用HTML编写文档的类
Main 测试程序行为的类

4.2 类图

4.3 示例代码

Builder类

是一个声明了编写文档的方法的抽象类。makeTitlemakeStringmakeTimes方法分别是编写标题、字符串、条目的方法。close方法是完成文档编写的方法。

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

Director类

使用Builder类中声明的方法来编写文档。
Director类的构造方法的参数是Builder类型的,但是实际上并不会将Builder类的实例作为参数传递给Director类。
construct方法是编写文档的方法,调用这个方法后就会编写文档。construct方法中所使用的方法都是在Builder类中声明的方法。

public class Director {
    private Builder builder;
    public Director(Builder builder) {              // 因为接收的参数是Builder类的子类
        this.builder = builder;                     // 所以可以将其保存在builder字段中
    }
    public void construct() {                       // 编写文档
        builder.makeTitle("Greeting");              // 标题
        builder.makeString("从早上至下午");         // 字符串
        builder.makeItems(new String[]{             // 条目
            "早上好。",
            "下午好。",
        });
        builder.makeString("晚上");                 // 其他字符串
        builder.makeItems(new String[]{             // 其他条目
            "晚上好。",
            "晚安。",
            "再见。",
        });
        builder.close();                            // 完成文档
    }
}

TextBuilder类

Builder类的子类,它的功能是使用纯文本编写文档,并以String返回结果。

public class TextBuilder extends Builder {
    private StringBuffer buffer = new StringBuffer();           // 文档内容保存在该字段中
    public void makeTitle(String title) {                       // 纯文本的标题
        buffer.append("==============================\n");      // 装饰线
        buffer.append("『" + title + "』\n");                   // 为标题添加『』
        buffer.append("\n");                                    // 换行
    }
    public void makeString(String str) {                        // 纯文本的字符串
        buffer.append('■' + str + "\n");                       // 为字符串添加■
        buffer.append("\n");                                    // 换行
    }
    public void makeItems(String[] items) {                     // 纯文本的条目
        for (int i = 0; i < items.length; i++) {
            buffer.append(" ・" + items[i] + "\n");            // 为条目添加・
        }
        buffer.append("\n");                                    // 换行
    }
    public void close() {                                       // 完成文档
        buffer.append("==============================\n");      // 装饰线
    }
    public String getResult() {                                 // 完成的文档
        return buffer.toString();                               // 将StringBuffer变换为String
    }
}

HTMLBuilder类

Builder类的子类,它的功能是使用HTML编写文档,返回结果是HTML文件的名字。

import java.io.*;
public class HTMLBuilder extends Builder {
    private String filename;                                                        // 文件名
    private PrintWriter writer;                                                     // 用于编写文件的PrintWriter
    public void makeTitle(String title) {                                           // HTML文件的标题
        filename = title + ".html";                                                 // 将标题作为文件名
        try {
            writer = new PrintWriter(new FileWriter(filename));                     // 生成 PrintWriter
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.println("<html><head><title>" + title + "</title></head><body>");    // 输出标题
        writer.println("<h1>" + title + "</h1>");
    }
    public void makeString(String str) {                                            // HTML文件中的字符串
        writer.println("<p>" + str + "</p>");                                       // 用<p>标签输出
    }
    public void makeItems(String[] items) {                                         // HTML文件中的条目
        writer.println("<ul>");                                                     // 用<ul>和<li>输出
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }
    public void close() {                                                           // 完成文档
        writer.println("</body></html>");                                           // 关闭标签
        writer.close();                                                             // 关闭文件
    }
    public String getResult() {                                                     // 编写完成的文档
        return filename;                                                            // 返回文件名
    }
}

Main类

测试程序。
由于TextBuilderHTMLBuilder都是Builder的子类,因此Dirctor仅仅使用Builder的方法即可编写文档,并不关心实际编写文档的到底是TextBuilder还是HTMLBuilder
正因为如此,我们必须在Builder中声明足够多的方法,以实现编写文档的功能,但并不包括TextBuilderHTMLBuilder中特有的方法。

public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            usage();
            System.exit(0);
        }
        if (args[0].equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Director director = new Director(textbuilder);
            director.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (args[0].equals("html")) {
            HTMLBuilder htmlbuilder = new HTMLBuilder();
            Director director = new Director(htmlbuilder);
            director.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "文件编写完成。");
        } else {
            usage();
            System.exit(0);
        }
    }
    public static void usage() {
        System.out.println("Usage: java Main plain      编写纯文本文档");
        System.out.println("Usage: java Main html       编写HTML文档");
    }
}

运行结果

java Main plain
==============================
『Greeting』
■从早上至下午
 ・早上好。
 ・下午好。
■晚上
 ・晚上好。
 ・晚安。
 ・再见。
==============================
java main html
Greeting.html文件编写完成。

摘自《图解设计模式》


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (1)