建造者模式的精髓在于:对构建过程进行解耦 一个对象的创建是非常复杂的,需要一步一步地操作,每个步骤都可能是有关联或依赖的, 最重要的是同一套建造流程是需要被不同的建造者复用的,因此需要分层抽象以松耦 目标:在不改变创建过程的前提下,可以创建出不同表象的对象
建造者模式的意图在于将一个对象复杂的建造过程(步骤多)从业务中分离出去,同时对建造过程进行抽象,从而使得在“建造”这一层面具有了可扩展性,这有就可以方便地通过切换建造过程而完成新型对象的创建,建造者模式将抽象出来的建造过程交由“指挥者”来管理,“指挥者”控制建造流程,并且通过指挥者获取建造的对象,用户不必再关系对象的创建过程。分离出来的建造过程,也可以被很好地管理,避免与具体的使用业务混杂在一起。
场景:软件系统通常都会有许多设置项,我们会通过一个Config对象来获取这些配置项目,比如端IP地址、口号、是否备份等,通常我们通过解析一个xml配置文件获取到这些属性值然后赋值给我们的Config对象。
用建造者模式来表述:
由于xml属性很多,建造过程复杂,不同的xml文件副本,属性值都不相同,这个时候,每一个xml文件副本都可以看作是一个具体的建造者,建造者只是可以获取到属性值,但却不知道如何完成Config对象的创建规则,指挥者就负责完成对象的创建过程,如此,对象的创建过程与表象分离开来!
示例代码:
class Config {
private String ip;
private int port;
private boolean bakEnabled;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isBakEnabled() {
return bakEnabled;
}
public void setBakEnabled(boolean bakEnabled) {
this.bakEnabled = bakEnabled;
}
@Override
public String toString() {
return "Config{" +
"ip='" + ip + '\'' +
", port=" + port +
", bakEnabled=" + bakEnabled +
'}';
}
}
abstract class ConfigBuilder {
protected Config config;
public ConfigBuilder() {
this.config = new Config();
}
public Config getConfig() {
return config;
}
public abstract void buildIp();
public abstract void buildPort();
public abstract void buildBakEnabled();
}
// 构建 指挥者
class ConfigBuildDirector {
private ConfigBuilder builder;
public void setBuilder(ConfigBuilder builder) {
this.builder = builder;
}
public void constructConfig() {
// 这里可以控制构建细节,比如许多判断逻辑和其它业务逻辑等
builder.buildIp();//第一步:构建IP地址
// others
builder.buildPort();//第二步:构建端口
// others
builder.buildBakEnabled();//第二步:构建是否需要备份
// others
}
}
class BakBuilder extends ConfigBuilder {
@Override
public void buildIp() {
config.setIp("127.0.0.1");
}
@Override
public void buildPort() {
config.setPort(80);
}
@Override
public void buildBakEnabled() {
config.setBakEnabled(true);//设置 “备份” 属性位true
}
}
class NoneBakBuilder extends ConfigBuilder {
@Override
public void buildIp() {
config.setIp("127.0.0.1");
}
@Override
public void buildPort() {
config.setPort(80);
}
@Override
public void buildBakEnabled() {
config.setBakEnabled(false);//设置 “备份” 属性位false
}
}
/**
* 建造者模式的精髓在于:对构建过程进行解耦
* 一个对象的创建是非常复杂的,需要一步一步地操作,每个步骤都可能是有关联或依赖的,
* 最重要的是同一套建造流程是需要被不同的建造者复用的,因此需要分层抽象以松耦
* 目标:在不改变创建过程的前提下,可以创建出不同表象的对象
*/
public class Test {
public static void main(String[] args) {
Config config;// 目标对象
// 建造指挥者,规划建造者的工作流程,一个系统中,通常只有一个建造指挥者
ConfigBuildDirector buildDirector = new ConfigBuildDirector();
// 建造者用以完成特定步骤的创建过程,不同的建造者的建造细节不相同
ConfigBuilder bakBuilder = new BakBuilder();//一个建造者
ConfigBuilder noneBakBuilder = new NoneBakBuilder();//另一个建造者
// 指挥第一个创建
buildDirector.setBuilder(bakBuilder);
buildDirector.constructConfig();
// 指挥第二个创建
buildDirector.setBuilder(noneBakBuilder);
buildDirector.constructConfig();
// 以下应该是用户获取目标对象的业务代码,用户将“Builder”交给“Director”指挥构建以后,
// 用户再通过“Builder”获取建造的目标对象
// 指挥完成建造后,通过建造者取出目标对象实例
config = bakBuilder.getConfig();
System.out.println(config);
// 指挥完成建造后,通过建造者取出目标对象实例
config = noneBakBuilder.getConfig();
System.out.println(config);
}
}