简易理解设计模式之:建造者模式——学习使用“链式调用”

介绍:

建造者模式属于创建型模式。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

类图:

在这里插入图片描述

Product(产品类):需要被构建的复杂对象
Builder(抽象建造者):规范产品的组建,一般是由子类实现具体的组件过程
ConcreteBuilder(具体建造者):实现抽象接口,构建复杂对象
Director(指挥者):构造一个使用Builder接口的对象

用法:

• 构建一个非常复杂的对象,如具有很多参数并且都有默认值的时候(代替setter方法构建对象,链式调用代码美观且简洁)
• 相同的方法,不同的执行顺序产生不同的结果时(指挥者中,buildPartA()、buildPartB()、buildPartC()的顺序不同,可能会产生不同的结果)
• 不同配置的构建对象,产生不同结果时(用不同的ConcreteBuilder构建对象,会产生不同的结果)

个人理解:
这个模式比较多用于链式调用分步组装对象,本质还是为了创建对象了。而它最大的特点在于创建的过程中的分步装配具有很大灵活性。如果一个对象灵活性要求比较高的话可以考虑使用此模式,否则可以考虑其它创建型模式。

例子:

在这个模式我觉得最大区别于其它创建型模式的特点就是链式调用多变的构造方法,为了更简单理解,首先带大家从传统的方法去实现一个简易计数器说明这个模式的用法,然后再用一个大众化的例子去创建一个UI控件。

需求1:实现一个具有加减乘除的简易计算器。
需求2:实现一个复杂UI控件。

1、实现一个计算器

1.1、实现一个产品类

   private int reult = 0;

为了强化此模式中的多变的构造方法特点,我们直接去掉产品类。计算器最终是得到一个经过一系列复杂运算的数,就是得到一个数。这个数就是我们的产品。

1.2、实现一个Builder类

public abstract class Builder {

    public abstract void add(int val);

    public abstract void substract(int val);

    public abstract void multiply(int val);

    public abstract void divide(int val);

    public abstract int getResult();

}

Builder类规范了计算器最终的结果是由加减乘除相关方法造成的。

1.3、实现ConcreteBuilder类

public class Math1Builder extends Builder {

    private int reult = 0;

    @Override
    public void add(int val) {
        reult += val;
    }

    @Override
    public void substract(int val) {
        reult -= val;
    }

    @Override
    public void multiply(int val) {
        reult *= val;
    }

    @Override
    public void divide(int val) {
        reult /= val;
    }

    @Override
    public int getResult() {
        return reult;
    }
}

好的,我们处理一下计算逻辑,Math1Builder是直接将入参运用到四则运算中。如果还有其它算法例如是入参的两倍等,可以新建一个Math2Builder然后类似这样写:

    @Override
    public void add(int val) {
        result += val * val;
    }

总之,这个计算器是怎么算是我们定好的。

1.4、实现一个Director类

public class Director {
    private Builder mBuilder;

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

    //构建对象
    public void create(int num1,int num2,int num3,int num4){
        mBuilder.add(num1);
        mBuilder.substract(num2);
        mBuilder.multiply(num3);
        mBuilder.divide(num4);
    }
}

Director中的Create方法控制了构建过程:按顺序做加减乘除。

1.5、实现结果

    public static void main(String[] args) {
        Builder builder = new Math1Builder();

        Director director = new Director(builder);
        director.create(3,2,4,2);
        System.out.println("输出一个数:"+builder.getResult());
    }
输出一个数:2

这个模式传统的做法就是这样实现了,我们分析一下:
• 最终得到的计算结果,就是我们的Product类。
• Builder类接受入参,实现加减乘除的运算逻辑,从而构建Product类。
• Director类控制加减乘除的运算顺序和运算次数,从而控制Builder类的运算逻辑。

在这过程中,每一步的调用次数、调用顺序都可能会影响最终的运算结果,所以算法是多变的。

1.6、通过链式调用优化
在实际开发中,我们会忽略掉Director角色。直接使用Builder来对对象进行组装。具体使用时在每个组件装配的过程中都返回自身,实现链式调用。先看看代码:

public class Builder {

    private int result = 0;

    public Builder add(int val) {
        result += val;
        return this;
    }

    public Builder substract(int val) {
        result -= val;
        return this;
    }

    public Builder multiply(int val) {
        result *= val;
        return this;
    }

    public Builder divide(int val) {
        result /= val;
        return this;
    }

    public int getResult() {
        return result;
    }
}

在这个例子中,Director、Builder、甚至是Product类都直接省略掉了,只剩下一个ConcreteBuilder。这样调用更加灵活:

public static void main(String[] args) {
    int result = new Builder().add(3).substract(2).multiply(4).divide(2).add(3).getResult();
    System.out.println("输出一个数:" + result);
}
输出一个数:5

我们清楚了解到链式调用就是建造者模式的一个重要特点。

2、实现一个UI控件

此模式常用于构建复杂对象,例如Android中UI控件使用此模式后能简化使用,很值得我们参考。

如比较著名的Glide框架:

Glide.with(Context context).load(Strint url).into(ImageView imageView);

AlertDialog.Builder:

AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setIcon(R.drawable.icon);
        builder.setTitle("标题");
        builder.setMessage("信息");
        builder.setPositiveButton("确定",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
        AlertDialog alertDialog = builder.create();
        alertDialog.show();

2.1、用伪代码实现AlertDialog.Builder(非源码)

public class AlertDialog {
    private final int icon;
    private final String message;
    private final String title;
    private final View.OnClickListener listener;

    private AlertDialog(Builder builder) {
        icon = builder.icon;
        message = builder.message;
        title = builder.title;
        listener = builder.listener;
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public static final class Builder {
        private int icon;
        private String message;
        private String title;
        private View.OnClickListener listener;

        private Builder() {
        }

        public Builder icon(int val) {
            icon = val;
            return this;
        }

        public Builder message(String val) {
            message = val;
            return this;
        }

        public Builder title(String val) {
            title = val;
            return this;
        }

        public Builder listener(View.OnClickListener val) {
            listener = val;
            return this;
        }

        public AlertDialog build() {
            return new AlertDialog(this);
        }
    }
}

AlertDialog就是我们的产品类,需要设置各种属性。
AlertDialog.Builder类同时充当Builder、ConcreteBuilder、Director。

2.2、调用

 AlertDialog mDialog = AlertDialog.newBuilder()
         .icon(R.mipmap.ic_launcher)
         .title("标题")
         .message("信息")
         .listener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
             }
         }).build();

这种复杂的构建过程,只需几行简单的代码就把AlertDialog创建出来了。例子2着重于简化创建复杂对象,模式隐藏了这种复杂的构建过程,大家可以尝试理解一下。

总结

• 这个模式的比较多用于通过链式调用分步组装对象,本质还是创建一个对象。
• 在组装的过程中的算法是多变的,每一步的调用次数、调用顺序都可能会影响最终结果。而组件的装配方式是稳定不变的,每个调用算法都是独立影响最终变化的。

感谢您的阅读~

推荐阅读

基础篇:
设计模式前篇之——UML类图必会知识点
设计模式前篇之——一起过一下面向对象的概念
创建型模式:
简易理解设计模式之:简单工厂模式——来试试接入支付功能
简易理解设计模式之:工厂方法模式——数据存储例子
简易理解设计模式之:抽象工厂模式——更换数据库例子
简易理解设计模式之:建造者模式——学习使用“链式调用”
简易理解设计模式之:原型模式——深、浅拷贝的概念
简易理解设计模式之:单例模式——单例模式的几种常用写法
结构型模式:
简易理解设计模式之:适配器模式——Android列表视图控件设计方式
简易理解设计模式之:桥接模式——穿衣服经典案例2
简易理解设计模式之:组合模式——实现View中的树状结构
简易理解设计模式之:装饰模式——穿衣服经典案例
简易理解设计模式之:外观模式——第三方SDK的帮助类
简易理解设计模式之:享元模式——五子棋游戏例子
简易理解设计模式之:代理模式——iOS视图控件设计方式
行为型模式:
简易理解设计模式之:策略模式——优化一下支付功能
简易理解设计模式之:模板方法模式——Android中的BaseActivity基类
简易理解设计模式之:观察者模式——监听与回调
简易理解设计模式之:状态模式——优化登录操作
简易理解设计模式之:备忘录模式——Word文档的工作原理
简易理解设计模式之:迭代器模式——遍历对象的好帮手
简易理解设计模式之:命令模式——实现命令的参数化配置
简易理解设计模式之:责任链模式——OA中请假流程示例
简易理解设计模式之:中介者模式——多人聊天室例子
简易理解设计模式之:解释器模式——语言和文法
简易理解设计模式之:访问者模式——员工考核例子

posted @ 2022-11-21 18:56  TwcatL_tree  阅读(120)  评论(0编辑  收藏  举报