建造者模式用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
它在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,因此此项设置为选填,这里还和抽象工厂模式做了个组合。从我的角度来说,这个模式在构造对象的时候既可以限定用户的输入,又相对灵活。从示例的角度来看这个例子并不是很好,不过它确实解决了实际问题~