图解设计模式 - Builder 模式

读书笔记 仅供参考

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

角色和 UML

Builder:负责定义用于生成实例的接口。
ConcreteBuilder:负责实现 Builder 角色的接口。定义了在生成实例时实际被调用的方法,还定义了获取最终生成结果的方法。
Director:负责使用 Builder 角色的接口来生成实例。
Client: 该角色来使用 Builder 模式(可以忽略)

这里写图片描述

例子

程序例子是实现采用两种方式编写文档,一个是纯文本,一个是 html 文本。写入最基本的文本,最后得到经过渲染的文本,在组装文本的过程中使用了 Builder 模式。

Builder 抽象类,担任上述的 Builder 角色,定义组装每一部分的接口。

public abstract class Builder {

    abstract void makeTitle(String title);
    abstract void makeString(String str);
    abstract void makeItems(String[] items);
    abstract void close();

}

Director 类,担任上述的 Director 角色,调用了 Builder 定义的接口,进行实例的组装。

public class Director {
    private Builder builder;

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

    public void construct() {
        builder.makeTitle("Greeting");
        builder.makeString(" 从早上至下午 ");
        builder.makeItems(new String[] {
                " 早上好。",
                " 下午好。",
        });
        builder.makeString(" 晚上 ");
        builder.makeItems(new String[] {
                " 晚上好 ",
                " 晚安。",
                " 再见。",
        });
        builder.close();
    }
}

TextBilder 类继承 Builder 类,担任上述 ConcreteBilder 角色,实现组装实例的接口细节。

public class TextBilder extends Builder {
    private StringBuffer buffer = new StringBuffer();
    @Override
    void makeTitle(String title) {
        buffer.append("===============================\n");
        buffer.append("[" + title + "]\n");
        buffer.append("\n");
    }

    @Override
    void makeString(String str) {
        buffer.append('◼' + str + "\n");
        buffer.append("\n");
    }

    @Override
    void makeItems(String[] items) {
        for(int i = 0; i < items.length; i++) {
            buffer.append("    ." + items[i] + "\n");
        }
        buffer.append("\n");
    }

    @Override
    void close() {
        buffer.append("===============================\n");
    }

    public String getResult() {
        return buffer.toString();
    }
}

和上者相同。

public class HtmlBuilder extends Builder {
    private String fileName;
    private PrintWriter writer;
    @Override
    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>");
    }

    @Override
    void makeString(String str) {
        writer.println("<p>" + str + "</p>");
    }

    @Override
    void makeItems(String[] items) {
        writer.println("<ul>");
        for(int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }

    @Override
    void close() {
        writer.println("</body></html>");
        writer.close();
    }

    public String getResult() {
        return fileName;
    }
}

Main 类,担任上述的 Client 角色,负责测试结果。

public class Main {
    public static void main(String[] args) {
        //生成纯文本
        TextBilder textBilder = new TextBilder();
        Director director = new Director(textBilder);
        director.construct();
        String result = textBilder.getResult();
        System.out.println(result);
        //生成 HTML
        HtmlBuilder htmlBuilder = new HtmlBuilder();
        Director director2 = new Director(htmlBuilder);
        director2.construct();
        String fileName = htmlBuilder.getResult();
        System.out.println(fileName + " 文件编写完成。");
    }

}

结果
这里写图片描述

UML
这里写图片描述

相关的设计模式

Template Method

在 Builder 模式中,Director 类定义了模板的流程。

Composite

有些情况下 Builder 模式生成的实例构成了 Composite 模式。

Abstract Factory

都用于生成复杂的实例。

Facade

Facade 通过组合内部模块向外部提过可以简单调用的接口。

扩展

Effective Java - 创建和销毁对象 - 遇到多个构造器参数时要考虑用构建器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值