设计模式 创建者模式

创建者模式:一步一步构造一个复杂对象。用户指定对象类型和内容就可以构建该复杂对象,不需知道具体对象细节。

包含角色

  1. Builder 抽象创建者
  2. ConcreteBuilder 具体创建者
  3. Director 指挥者:隔离客户和创建者,控制了产品的生成。客户提供要建造的类型,指挥官调用对应的创建者创建出对应的对象。
  4. Product 产品角色
    核心:同样的创建过程,不同的表示构造

适用于

  1. 创建复杂对象的算法独立于该对象的组成部分以及装配方式时
  2. 构造过程必须被允许构造的对象有不同的表示时
  3. Director:构造一个使用builder接口的对象

Builder:为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder:

  1. 实现Builder接口以构造和装配该产品的各个部件
  2. 定义明确创建的表示
  3. 提供检索product的接口

Example

利用创建者模式创建文件

  • 含有标题
  • 含有字符串
  • 含有一些有项目符号的项目

Builder规定如何装配这些元素,组成一个文件(有不同的组合方式【不同的表示构造】)
Director类利用这个方法产生一份具体的文件。

  • Director使用TextBudiler产生一个一般格式的文本文件
  • Director使用HTMLBuilder产生一个HTML格式的文件

类图

设计模式 创建者模式_第1张图片

client并不知道Builder接口有啥方法,只是调用Director的构造方法。
Director只有一个builder类。但是Director不知道调用buidler的哪个子类。

循序渐进地组合(不是一下子就生成一个对象!不是一下子就生成一个对象!不是一下子就生成一个对象!)一个较为复杂的对象实例,组合装配的过程在Director的Builder里面。生成时,才从Direcrtor中取出

每个ConcreteBuilder(XXXBuilder)只需要写一次。不同的Director就可以在相同部件的集合上,构造不同的Product

实现代码

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

Director里面可以看到,所有类型的文件的内容都是一样的,只是类型不同。
Director利用客户传来的“对象类型”来使用对应的builder来创建对应类型的文件。

public class Director {
    private Builder builder;
    public Director(Builder builder){ //客户手动指定要创建的对象类型
        this.builder = builder;
    }

    public Object construt(){//文件的内容都是一样的,只是文件格式类型不一样 html txt
        builder.makeTitle("文件的标题");
        builder.makeString("从早上到白天結束");      // 字串
        builder.makeItems(new String[]{           // 项目
                "早安。",
                "午安。",
        });
        builder.makeString("到了晚上");              // 另一个字串
        builder.makeItems(new String[]{             // 另一个项目
                "晚安。",
                "祝你有个好梦。",
                "再见。",
        });
        return builder.getResult();                 // 完成的文件就是返回值
    }

}

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

public class HTMLBuilder extends Builder{
    private String filename;
    private PrintWriter writer;

    @Override
    public Object getResult() {
        writer.println("");              // 关闭标签
        writer.close();                                // 关闭文件
        return filename;                               // 返回文件名
    }

    @Override
    public void makeItems(String[] items) {
        writer.println("
    "); // 以
    • 输出 for (int i = 0; i < items.length; i++) { writer.println("
    • " + items[i] + "
    • "); } writer.println("
    "
    ); } @Override public void makeString(String str) { writer.println("

    " + str + "

    "
    ); } @Override public void makeTitle(String title) { filename = title+".html"; try { writer = new PrintWriter(new FileWriter(filename)); } catch (IOException e) { e.printStackTrace(); } writer.println(""</span> <span class="token operator">+</span> title <span class="token operator">+</span> <span class="token string">""); // 输出标题 writer.println("

    " + title + "

    "
    ); } }

用于生成html文件

public class TextBuilder extends Builder{
    private StringBuffer buffer = new StringBuffer();

    @Override
    public Object getResult() {
        buffer.append("==============================\n");	// 花边
        return buffer.toString();		// 把StringBuffer转换成String
    }

    @Override
    public void makeItems(String[] items) {
        for (int i = 0; i < items.length; i++) {
            buffer.append("?" + items[i] + "\n");	// 有?的项目
        }
        buffer.append("\n");
    }

    @Override
    public void makeString(String str) {
        buffer.append('■' + str + "\n");		// 有■的字串
        buffer.append("\n");				// 空行
    }

    @Override
    public void makeTitle(String title) {
        buffer.append("==============================\n");	// 花边
        buffer.append("『" + title + "』\n");			// 有『』的标题
        buffer.append("\n");
    }
}

下面是我自己的水印文件

public class ViendeTxtBuilder extends Builder{
    private StringBuffer buffer = new StringBuffer();

    @Override
    public Object getResult() {
        buffer.append("over over over for viendeTXT");
        return buffer.toString();
    }

    @Override
    public void makeTitle(String title) {
        buffer.append("viende's"+title);
    }

    @Override
    public void makeString(String str) {
        buffer.append("viende"+str);
    }

    @Override
    public void makeItems(String[] items) {
        for(String item:items){
            buffer.append("Viende"+item);
        }
        buffer.append("over item!");
    }
}

Client文件`

public class Client {
    public static void main(String[] args) {
        Director directorTXT = new Director(new TextBuilder());
        //客户需要txt文件
        String res = (String) directorTXT.construt();
        System.out.println(res);

        //客户需要html文件
        Director directorHTML = new Director(new HTMLBuilder());
        String filename =(String) directorHTML.construt();
        System.out.println("已将产生HTML文件"+filename);

        //我创建的具体的builder(每个内容都会跟上'viende'这个单词的水印)
        Director directorViendeTxt = new Director(new ViendeTxtBuilder());
        String viendeStr =(String) directorViendeTxt.construt();
        System.out.println("已经产生含viende水印的文件,内容为:");
        System.out.println(viendeStr);

    }
}

测试结果:

设计模式 创建者模式_第2张图片
在这里插入图片描述
设计模式 创建者模式_第3张图片

创建者模式的优缺点:

优点

  1. 客户端不需要知道对象的内部组成,只需提供对象类型(对应的ConcreteBuilder),即可完成对象的创建获取
  2. 每个具体创建者都独立,与其他创建者无关,可以方便的替换具体创建者或者增加新的创建者。
  3. 产品本身和产品的创建过程解耦

缺点

  1. 建造者模式所创建的产品一般具有较多的共同点,组成成分相似。但是产品之间的差异如果很大,不适合使用建造者模式。
  2. 如果产品内部变化负载,会导致定义太多具体的建造者来实现变化,让系统变得过于庞大
    ‘’

你可能感兴趣的:(设计模式,java)