创建型模式之建造者模式(Builder)

来源:互联网 发布:软件开发阶段任务 编辑:程序博客网 时间:2024/05/18 01:40

建造者模式的精髓在于:对构建过程进行解耦一个对象的创建是非常复杂的,需要一步一步地操作,每个步骤都可能是有关联或依赖的,最重要的是同一套建造流程是需要被不同的建造者复用的,因此需要分层抽象以松耦目标:在不改变创建过程的前提下,可以创建出不同表象的对象

建造者模式的意图在于将一个对象复杂的建造过程(步骤多)从业务中分离出去,同时对建造过程进行抽象,从而使得在“建造”这一层面具有了可扩展性,这有就可以方便地通过切换建造过程而完成新型对象的创建,建造者模式将抽象出来的建造过程交由“指挥者”来管理,“指挥者”控制建造流程,并且通过指挥者获取建造的对象,用户不必再关系对象的创建过程。分离出来的建造过程,也可以被很好地管理,避免与具体的使用业务混杂在一起。


场景:软件系统通常都会有许多设置项,我们会通过一个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);    }}