GOF设计模式(05)建造者模式 设计模式的征途—6.建造者(Builder)模式

简介

一、定义

1、概念

  • 建造者模式(Builder):将一个复杂对象的构建与它的表示相分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

2、理解

  • 将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端只需要知道所需的建造者即可
  • 不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,增加新的建造者非常方便

二、组件

  • Builder(抽象建造者):为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法用于创建复杂对象的各个部件,另一类方法用于返回复杂对象。
  • ConcreteBuilder(具体建造者):实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。
  • Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
  • Director(指挥者):它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系(组合),可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。

三、结构图

 

示例

一、产品类

class Product  {

       private  String partA; //定义部件,部件可以是任意类型,包括值类型和引用类型

       private  String partB;

       private  String partC;

       //partA的Getter方法和Setter方法省略

       //partB的Getter方法和Setter方法省略

       //partC的Getter方法和Setter方法省略

}

二、建造者

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;
       }
}

三、指挥者

class Director {
       private  Builder builder;
       public  Director(Builder builder) {
              this.builder=builder;
       }
      
       public  void setBuilder(Builder builder) {
              this.builder=builer;
       }      
       //产品构建与组装方法
       public Product construct() {
              builder.buildPartA();
              builder.buildPartB();
              builder.buildPartC();
              return builder.getResult();
       }
}

四、测试代码

public class Client{
    public static void main(String[] args){
        Builder  builder = new ConcreteBuilder(); //可通过配置文件实现
        Director director = new  Director(builder);
        Product product = director.construct();
    }
}

 

总结

一、优缺点

1、优点

  • 客户端不需要知道产品内部的组成细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 具体建造者相对独立,增加新的具体建造者无需修改原有类库的代码,系统扩展比较方便,符合开闭原则。
  • 可以更加精细地控制产品的创建过程 -> 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

2、缺点

  • 对于所创建的产品有一定限制:一般这些产品都具有一些较多的共同点,其组成部分相似。如果差异性很大,那么则不适合使用建造者模式。
  • 如果产品的内部结构复杂多变,可能会需要定义很多具体构建者来实现这些变化,会导致系统变得庞大,增加系统的理解难度和运行成本。

二、使用场景

  • 需要生成的产品对象由复杂的内部结构,这些产品对象通常包含多个成员变量。
  • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

三、建造者模式和抽象工厂

  • 建造者模式与抽象工厂模式有点相似,但是建造者模式返回一个完整的复杂产品,而抽象工厂模式返回一系列相关的产品
  • 在抽象工厂模式中,客户端通过选择具体工厂来生成所需对象,而在建造者模式中,客户端通过指定具体建造者类型并指导Director类如何去生成对象,侧重于一步步构造一个复杂对象,然后将结果返回
  • 如果将抽象工厂模式看成一个汽车配件生产厂,生成不同类型的汽车配件,那么建造者模式就是一个汽车组装厂,通过对配件进行组装返回一辆完整的汽车

四、关于Director的进一步讨论

1、省略 Director:直接在builder里引入construct 方法

abstract class ActorBuilder {
    protected static Actor actor = new Actor();
    public abstract void buildType();
    public abstract void buildSex();
    public abstract void buildFace();
    public abstract void buildCostume();
    public abstract void buildHairstyle();

    public static Actor construct(ActorBuilder ab) {
        ab.buildType();
        ab.buildSex();
        ab.buildFace();
        ab.buildCostume();
        ab.buildHairstyle();
        return actor;
    }
}

2、引入钩子方法:精确控制对象的创建过程

abstract class ActorBuilder {
    protected Actor actor = new Actor();

    public abstract void buildType();

    public abstract void buildSex();

    public abstract void buildHairstyle();

    //钩子方法
    public boolean isBareheaded() {
        return false;
    }

    public Actor createActor() {
        return actor;
    }
}

class DevilBuilder extends ActorBuilder {
    public void buildType() {
        actor.setType("恶魔");
    }

    public void buildSex() {
        actor.setSex("妖");
    }

    public void buildHairstyle() {
        actor.setHairstyle("光头");
    }

    //覆盖钩子方法
    public boolean isBareheaded() {
        return true;
    }
}

class ActorController {
    public Actor construct(ActorBuilder ab) {
        Actor actor;
        ab.buildType();
        ab.buildSex();
        //通过钩子方法来控制产品的构建
        if (!ab.isBareheaded()) {
            ab.buildHairstyle();
        }
        actor = ab.createActor();
        return actor;
    }
}

*****************************************参考************************************

猜你喜欢

转载自www.cnblogs.com/stanwuc/p/10897903.html