构建者模式(Builder Pattern)

组装复杂的实例

1.基本介绍

对于组件复杂的实例时,很难一气呵成,而且实例形式不定,会经常性变化,这时候就需要创建组成实例的各个部分,然后根据具体需求,分阶段将其组装起来,如同活字印刷术,或者建造建筑。


2.具体实现

Builder类:

/**
 * @author Jay
 * @date 2019/6/25 22:41
 * @description 声明编写文档方法的抽象类
 */
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类:

将抽象父类或者接口作为参数传递,实现解耦。方法中具体制定了整个实例的拼接的规范,如同设计图纸,规定每一块材料如何具体拼接。

/**
 * @author Jay
 * @date 2019/6/25 22:42
 * @description 使用Bulider中声明方法写文档
 */
public class Director {
    /**
     * 可将子类实例保存其中
     */
    private Builder builder;

    /**
     * 抽象类无法实例化对象,可以接收其子类实例.
     *
     * @param builder
     */
    public Director(Builder builder) {
        super();
        this.builder = builder;
    }

    /**
     * 编写文档
     */
    public void construct() {
        builder.makeTitle("Greeting");
        builder.makeString("从早到下午");
        builder.makeItems(new String[]{
                "早上好",
                "下午好"
        });
        builder.makeString("晚上好");
        builder.makeItems(new String[]{
                "晚上好",
                "再见!"
        });
        builder.close();
    }

}

TextBuilder类:

继承抽象父类,具体实现其中的抽象方法,如同建筑中将每一块砖,每一个模型造好,然后设计者利用这些组件区设计整个建筑。

/**
 * @author Jay
 * @date 2019/6/25 22:44
 * @description Builder子类, 纯文本写文档
 */
public class TextBuilder extends Builder {
    private StringBuffer buffer = new StringBuffer();

    /**
     * 标题
     *
     * @param title
     */
    @Override
    public void makeTitle(String title) {
        buffer.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        buffer.append("(" + title + ")\n");
        buffer.append("#############################\n");
        buffer.append("\n");
    }

    /**
     * 内容
     *
     * @param str
     */
    @Override
    public void makeString(String str) {
        buffer.append("$" + str + "\n");
        buffer.append("\n");
    }

    /**
     * 条目
     *
     * @param items
     */
    @Override
    public void makeItems(String[] items) {
        for (String string : items) {
            buffer.append("##" + string + "\n");
        }
        buffer.append("\n");
    }

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

    /**
     * 输出文档
     *
     * @return
     */
    public String getResult() {
        return buffer.toString();
    }
}

Main:

/**
 * @author Jay
 * @date 2019/6/25 22:51
 * @description
 */
public class Main {
    public static void main(String[] args) {
        //实例化组件对象
        TextBuilder tb =  new TextBuilder();
        //将其作为参数传递进去,组装方法调用组件对象的具体组件去组装
        Director di = new Director(tb);
        //调用组装方法
        di.construct();
        System.out.println(tb.getResult());

    }
}

3.主要角色

Builder(建造者)

定义用来生成实例方法的接口,其中定义各种组件。

ConcreteBuilder(具体建造者)

具体实现接口中的方法,定义了在生成实例时实际被调用的方法,每一个组件的具体实现.
其中还有获取最终结果的方法。

Director(监工)

负责使用Builder接口来生成实例,接收Builder参数,只调用Builder接口中被定义的方法,不论ConcreteBuilder中如何具体实现组件,都可以正常实现,就如同设计图纸一样,不管组件如何具体实现,只要实现了接口,都可以通过接口方法来进行组装,接口,是一种规范!


4.模式改进

上述例子中,可以将Director类省略,直接生成实例,通过链式结构,随意组装对象,并不需要通过修改Director中的对象生成方法,从而进一步解耦。

Builder:

/**
 * @author Jay
 * @date 2019/6/25 23:03
 * @description 声明编写文档方法的接口
 */
public interface Builder {
    Builder makeTitle(String title);

    Builder makeString(String str);

    Builder makeItems(String[] items);

    Builder close();
}

TextBuilder类:

/**
 * @author Jay
 * @date 2019/6/25 23:06
 * @description
 */
public class TextBuilder implements Builder {
    /**
     * 文档内容保存在其中
     */
    private StringBuffer buffer = new StringBuffer();

    public TextBuilder() {
        super();
    }

    @Override
    public Builder makeTitle(String title) {
        buffer.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        buffer.append("(" + title + ")\n");
        buffer.append("#############################\n");
        buffer.append("\n");
        //直接将实例本身返回,实现链式调用
        return this;
    }

    @Override
    public Builder makeString(String str) {
        buffer.append("$" + str + "\n");
        buffer.append("\n");
        return this;
    }

    @Override
    public Builder makeItems(String[] items) {
        for (String string : items) {
            buffer.append("##" + string + "\n");
        }
        buffer.append("\n");
        return this;
    }

    @Override
    public Builder close() {
        buffer.append("%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
        return this;
    }

    public String getResult() {
        //变化为String
        return buffer.toString(); 
    }
}

main

/**
 * @author Jay
 * @date 2019/6/25 23:11
 * @description
 */
public class Main {
    public static void main(String[] args) {
        TextBuilder tb = (TextBuilder) new TextBuilder().makeTitle("这是一个标题")
                .makeString("这是一个字符串").makeItems(new String[]{"这是第一条数据"})
                .makeItems(new String[]{"这是第二条数据",
                        "这是第三条数据",
                        "这是第四条数据"
                }).makeTitle("再加一个标题").makeString("最后一个字符").close();
        System.out.println(tb.getResult());
    }
}

(这是一个标题)
#############################

$这是一个字符串

##这是第一条数据

##这是第二条数据
##这是第三条数据
##这是第四条数据

(再加一个标题)
#############################

$最后一个字符

%%%%%%%%%%%%%%%%%%%%%%%%%%%%

省略制定设计图纸的类,直接在测试类中生成具体所需的类,实现链式调用,进一步解耦,实例生成也更为灵活,不过每一个方法都会返回实例,并且为公有方法,外界可以直接调用,因此可以改进使用内部类,更为安全。

/**
 * @author Jay
 * @date 2019/6/25 23:14
 * @description
 */
public class Student {
    private final int age;
    private final int weight;
    private final int height;
    private final int size;
    private final String name;

    @Override
    public String toString() {
        return "Student [age=" + age + ", weight=" + weight + ", height=" + height + ", size=" + size + ", name=" + name
                + "]";
    }

    /**
     * 创建静态内部类
     * 属性都有默认值,若是未定义则是默认值,再次定义会将其覆盖
     */
    public static class Bulider {
        private final int age;
        private final int weight;
        private int height = 0;
        private int size = 0;
        private String name = null;

        public Bulider(int age, int weight) {
            this.age = age;
            this.weight = weight;
        }

        public Bulider heiht(int val) {
            //每次返回本身实例,则可以实现属性随意组合,
            height = val;
            return this;
        }

        public Bulider size(int val) {
            size = val;
            return this;
        }

        public Bulider name(String val) {
            name = val;
            return this;
        }

        public Student bulid() {     //最后调用此方法会生成所需实例
            return new Student(this);
        }
    }

    private Student(Bulider bulider) {   //私有构造属性,外界无法调用,内部类可以调用
        age = bulider.age;
        height = bulider.height;
        size = bulider.size;
        name = bulider.name;
        weight = bulider.weight;
    }

    public static void main(String[] args) {
        Student stu = new Student.Bulider(18, 2).heiht(20).name("张三").bulid();
        System.out.println(stu);
    }
}

To GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值