设计模式之建造者模式

概述

建造者模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 [构建与表示分离,同构建不同表示]

假如一个对象的构建很复杂,需要很多步骤。则可以使用建造者模式,将其构建对象和组装成一个对象这两步给分开来。构建部分为(builder)和组织部分(director),实现了构建和装配的解耦。

不同的构建器,相同的装配也可以做出不同的对象。

相同的构建器,不同的装配顺序也可以做出不同的对象。

UML

  • Dirextor: 指挥者类,用于统一组装流程
  • Builder:抽象Builder类,规范产品的组建,一般是由子类实现。
  • ConcreteBulider: 抽象Builder类的实现类,实现抽象Builder类定义的所有方法,并且返回一个组建好的对象
  • Product: 产品类

适用场合

  • 相同的方法,不同的执行顺序,产生不同的事件结果时。
  • 多个部件或零件装配到一个对象中,但是产生的运行结果又不同。
  • 产品类非常复杂,或者产品中的调用顺序不同产生不同的作用时,就可以考虑建造者模式。
  • 当初始化一个对象特别复杂,参数多,且很多参数都具有默认值时。

例子

以生产PC为例,这里我们假设生产一台PC只需三个步骤,创建cpu、创建内存、创建显示器,将三个步骤抽象成一个Builder,且该Builder有一个创建待加工的产品的方法和返回成品的方法;

以联想电脑和惠普电脑为例,认为它们在生产电脑的过程中,以上三个步骤的实现是不一致的,对应着具体的HPBuilder和LenovoBuilder;

同时,我们把电脑产品封装成Computer类,其拥有cpu、内存、显示器三个属性;

然后,再创建一个指挥者类Director,其拥有一个建造者对象和建造PC产品的方法construct,该方法通过具体建造者对象,依次执行每个步骤,最后返回建造完成的产品对象;

类图:

代码实现:

产品角色

package com.dyleaf.create.BuilderPattern;

public class Computer {

    private String cpu;
    private String ram;
    private String monitor;
    /**
     * @return the cpu
     */
    public String getCpu() {
        return cpu;
    }
    /**
     * @param cpu the cpu to set
     */
    public void setCpu(String cpu) {
        this.cpu = cpu;
    }
    /**
     * @return the ram
     */
    public String getRam() {
        return ram;
    }
    /**
     * @param ram the ram to set
     */
    public void setRam(String ram) {
        this.ram = ram;
    }
    /**
     * @return the monitor
     */
    public String getMonitor() {
        return monitor;
    }
    /**
     * @param monitor the monitor to set
     */
    public void setMonitor(String monitor) {
        this.monitor = monitor;
    }

    public String toString(){
        return "PC:" + this.cpu + ", " + this.ram + ", " + this.monitor;
    }
}

抽象建造者

package com.dyleaf.create.BuilderPattern;

public abstract class Builder {
    private Computer pc ;
    public abstract void buildCpu();
    public abstract void buildRam();
    public abstract void buildMonitor();


    public void createComputer(){
        this.pc = new Computer();
    }
    public Computer getComputer(){
        return this.pc;
    }
}

两个具体建造者

package com.dyleaf.create.BuilderPattern;

public class LenovoBuilder extends Builder{
    @Override
    public void buildCpu() {
        System.out.println("lenovo: build cpu start...");
        this.getComputer().setCpu("lenovo cpu");
        System.out.println("lenovo: build cpu end...");
    }

    @Override
    public void buildRam() {
        System.out.println("lenovo: build ram start...");
        this.getComputer().setRam("lenovo ram");
        System.out.println("lenovo: build ram end...");

    }

    @Override
    public void buildMonitor() {
        System.out.println("lenovo: build monitor start...");
        this.getComputer().setMonitor("lenovo monitor");
        System.out.println("lenovo: build monitor end...");

    }
}
package com.dyleaf.create.BuilderPattern;

public class HPBuilder extends Builder{

    @Override
    public void buildCpu() {
        System.out.println("hp: build cpu start...");
        this.getComputer().setCpu("hp cpu");
        System.out.println("hp: build cpu end...");
    }

    @Override
    public void buildRam() {
        System.out.println("hp: build ram start...");
        this.getComputer().setRam("hp ram");
        System.out.println("hp: build ram end...");

    }

    @Override
    public void buildMonitor() {
        System.out.println("hp: build monitor start...");
        this.getComputer().setMonitor("hp monitor");
        System.out.println("hp: build monitor end...");

    }

}

指挥者

package com.dyleaf.create.BuilderPattern;

public class Director {

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

    public Computer construct(){
        this.builder.createComputer();
        this.builder.buildCpu();
        this.builder.buildRam();
        this.builder.buildMonitor();
        return this.builder.getComputer();
    }

    /**
     * @return the builder
     */
    public Builder getBuilder() {
        return builder;
    }

    /**
     * @param builder the builder to set
     */
    public void setBuilder(Builder builder) {
        this.builder = builder;
    }
}

Test

package com.dyleaf.create.BuilderPattern;

public class Test {
    public static void main(String[] args) {
        Builder hpBuilder = new HPBuilder();
        Director director = new Director(hpBuilder);
        Computer hpPC = director.construct();
        System.out.println(hpPC.toString());

        Builder lenovoBuilder = new LenovoBuilder();
        director.setBuilder(lenovoBuilder);
        Computer lenovoPC = director.construct();
        System.out.println(lenovoPC.toString());

    }
}

运行结果如下,相同的指挥者使用不同的建造者创建了不同的产品:

优缺点

优点

  • 使用Builder会导致写两遍相关属性的代码和SETTER方法(Builder中一次,Director中一次),但是代码的可读性和可用性大大提高。
  • 单个builder构建多个对象时Builder参数可在创建期间进行调整,还可以根据对象不同而进行改变。

缺点

  • 使用Builder模式是肯定会增加代码量的。- 一般需要嵌套到类中,容易忘记给某个属性添加builder支持。

see source code

posted @ 2018-03-05 01:40  Dyleaf  阅读(149)  评论(0编辑  收藏  举报