设计模式5之建造者模式

2022-05-05 17:39:43 浏览数 (2)

一个复杂的对象往往由多个子部件按一定的步骤组成。例如,汽车由发动机、轮胎、方向盘等部件组成的。

组成对象的各个部件可以灵活选择,而创建步骤大同小异。我们可以用建造者模式很好的描述该类产品的创建。

什么是建造者模式呢

“Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分 离,使得同样的构建过程可以创建不同的表示。) ”

建造者模式中,将一个复杂的对象分解成多个简单的对象,产品的组成部分不变,但每个简单的对象内部是可以灵活多变的。

我们先不谈建造者模式的优缺点,现在来了解下建造者模式的的组成结构。

建造者模式主要由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成。这4个要素的说明如下:

  • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
  • 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()
  • 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

这几种要素关系如下:

建造者模式

代码实现

产品类Product

代码语言:javascript复制
@Data
public class Product {
    private String partA;
    private String partB;
    private String partC;

    public void show(){
        String partA = getPartA();
        String partB = getPartB();
        String partC = getPartC();
        System.out.println("这可能是东半球最好的产品...");
        Console.log("组成结构:{},{},{}",partA,partB,partC);
    }
}

Product类包括3个部件字段,以及一个展示方法show()

建造者抽象类Builder

代码语言:javascript复制
public abstract class Builder {
 protected Product product = new Product();

 public abstract void buildPartA();

 public abstract void buildPartB();

 public abstract void buildPartC();

 public Product getResult() {
  return product;
 }
}

抽象类Builder包括3个抽象方法,以及一个获取Product对象的方法。

指挥者类Director

代码语言:javascript复制
public class Director {
    private Builder builder;

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

    public Product construct(){
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

Director类内部包含Director构造函数用于传入Builder对象,construct()方法主要调用了建造类里面的方法,并返回Product对象。

ConcreteBuilder继承抽象建造者,实现里面的方法。

代码语言:javascript复制
public class ConcreteBuilder extends Builder {
    @Override
    public void buildPartA() {
        product.setPartA("建造 PartA");
    }

    @Override
    public void buildPartB() {
        product.setPartB("建造 PartB");
    }

    @Override
    public void buildPartC() {
        product.setPartC("建造 PartC");
    }
}

调用类Client

代码语言:javascript复制
public class Client {
    public static void main(String[] args){
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product construct = director.construct();
        construct.show();
    }
}

测试结果:

代码语言:javascript复制
这可能是东半球最好的产品...
组成结构:建造 PartA,建造 PartB,建造 PartC

有代码可知:

“首先创建了一个建造者,建造者里面有各种功能,为产品属性赋值 然后创建了一个指挥者,指挥者调用建造者功能从而能获得产品 ”

由建造模式我们可知,产品不直接创建,而是通过指挥者指挥建造者创建。这个是不是和工厂模式很像呢,但是需要注意,建造者模式比工厂模式要复杂。

当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。

关于建造者模式的思考

那么建造者模式有哪些优点呢?

同工厂模式一样,客户端不用知道产品内部的组成细节,就能获得产品;建造者与建造者之间是相互独立的。有利于系统扩展;并且修改某个建造者不会对其他模块产生影响。

那么什么时候使用建造者模式呢?《设计模式之禅》里写道:

“● 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。 ● 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可 以使用该模式。 ● 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建 造者模式非常合适。 ● 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程 中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方 法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建 过程,本身已经违反设计的最初目标。 ”

0 人点赞