[设计模式]建造者模式

      建造者模式用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

      它在Android中的应用还是很多的,比如说:AlertDialog.Builder、Notification.Builder、AudioFocusRequest.Builder等,可以比较以下Android新旧的版本,Android SDK18之前的创建方法是new一个对象,之后的版本使用就变成了建造者,可见建造者模式创建对象的方式还是值得学习的。

      下面介绍一下建造者模式的具体内容:

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

何时使用:一些基本部件不会变,而其组合经常变化的时候。

如何解决:将变与不变分离开。

关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。

优点: 1、建造者独立,易扩展。 2、便于控制细节风险。

缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。

使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。

注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

      在我的应用中用到的该模式的地方:在构建某个消息类型的时候需要用户填写一些内容并选择一种模式,这个时候使用建造者模式让用户去选择。下面上代码:

public final class LightEffectCommandFactory implements CommandFactory {

    private Domain domain;
    private Operation operation;
    private Integer value;

    /**
     * @param domain    功能,包含亮度、色彩度、对比度、色温四种功能
     *                  不能为空,如果为空最后组装出来的Command会为空
     * @param operation 操作,目前包含INCREASE、DECREASE、QUERY、MAX、MIN、MID、SET,当为SET时会首先设置默认值为50
     *                  不能为空,如果为空最后组装出来的Command会为空
     */
    public LightEffectCommandFactory(@NonNull Domain domain, @NonNull Operation operation) {
        this.domain = domain;
        this.operation = operation;
        if (operation != null && operation == Operation.SET) {
            value = 50;
        }
    }

    /**
     * @param value 当operation为SET时需要设置值
     *              不设置的话会使用默认值50
     * @return
     */
    public LightEffectCommandFactory setValue(int value) {
        this.value = value;
        return this;
    }

    /**
     * @return 灯效Command
     */
    @Override
    public Command assembleCommand() {
        if (domain == null || operation == null) return null;
        Command command = null;
        LightEffectCommandParameter lightEffectCommandParameter = new LightEffectCommandParameter();
        lightEffectCommandParameter.setOperation(operation.value);
        String query = this.domain.describe + this.operation.describe;
        if (operation == Operation.SET && value != null) {
            query += value;
            lightEffectCommandParameter.setValue(value);
        }
        command = new Command(domain.value, query, lightEffectCommandParameter);
        return command;
    }

    public enum Domain {

        BRIGHTNESS("brightness", "亮度"), COLOR_DEGREE("color_degree", "色彩度调节"), CONSTRACT_RATIO("constract_ratio", "对比度调节"), COLOR_TEMPERATURE("colortemp", "色温");

        private String value;
        private String describe;

        Domain(String value, String describe) {
            this.value = value;
            this.describe = describe;
        }
    }

    public enum Operation {

        INCREASE("INCREASE", "增加"), DECREASE("DECREASE", "减少"), QUERY("QUERY", "查询"), MAX("MAX", "最大"), SET("SET", "设置为"), MIN("MIN", "最小"), MID("MID", "中等");

        private String value;
        private String describe;

        Operation(String value, String describe) {
            this.value = value;
            this.describe = describe;
        }
    }
}

      这里需要用户必填的参数在构造函数里就要求用户填写了,当operation是SET的时候才需要用户去设置value,因此此项设置为选填,这里还和抽象工厂模式做了个组合。从我的角度来说,这个模式在构造对象的时候既可以限定用户的输入,又相对灵活。从示例的角度来看这个例子并不是很好,不过它确实解决了实际问题~
 

发布了61 篇原创文章 · 获赞 2 · 访问量 8719

猜你喜欢

转载自blog.csdn.net/woaily1346/article/details/90577846