当先锋百科网

首页 1 2 3 4 5 6 7

概述

创建者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

与工厂模式相比,创建者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——指挥类(负责流程控制)。

工厂模式:是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;每一次工厂对象被调用时都会返回一个完整的产品对象,而客户端有可能会决定把这些产品组装成一个更大更复杂的产品,也有可能不会
创建者模式:创建者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给指挥类。由指挥类负责将各个组件按照特定的规则组建为产品,组装过程就发生在创建者角色内部,然后将组建好的产品交付给客户端。

工厂模式返回不同组成属性,而建造者模式则把它们组装起来

涉及角色

  • Builder
    抽象创建者角色:对复杂对象的创建过程加以抽象,给出一个抽象接口,以规范产品对象的各个组成部分的建造。引入抽象创建者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。
  • ConcreteBuilder
    具体创建者角色:实现Builder接口,针对不同的业务逻辑,具体化复杂对象的各个部分的创建。在建造过程完成后,提供产品的实例。一般至少会有两个抽象方法,一个用来建造产品(组装产品的多个部分),一个是用来返回产品
  • Director
    指挥者:调用具体创建者来创建复杂对象的各个部分,在指导者中不设计具体产品的信息,只负责保证对象各部分完整创建或者按某种顺序创建。一般来说,该类被用来封装程序中易变的部分
  • 对象:要创建的复杂对象,一般来说包含多个部分。

UML

这里写图片描述

使用场景

  • 创建一些复杂对象时,这些对象的内部组成部分之间的建造顺序是稳定的,但对象的内部组成构建面临着复杂的变化。
  • 要创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品

优点

  • 使用创建者模式可以使客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 便于控制细节风险具体的创建者类之间是相互独立的,这有利于系统的扩展,可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 具体的创建者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

缺点

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

代码示例

使用创建者模式有一个隐含的前提,那就是这些产品有共同的特性,也就是说可以用共同的接口实现。另外需要主要的是在Builder中返回的是产品的共同父类,这样才能满足多个产品的返回都正常

比如:一个加工厂包含如下角色:工厂厂长(Director)、员工(ConcreteBuilder)、生产流程规范(Abstractbuilder)、具体生产的产品(Product)

package com.designpattern.builder;

public interface Product {

    public void createProductAttributes(String attribute);
    public void showAttributes() ;

}
package com.designpattern.builder;

import java.util.ArrayList;
import java.util.List;

public class Pen implements Product {
    private List<String> attributes = new ArrayList<String>();

    @Override
    public void createProductAttributes(String attbute) {
        // TODO Auto-generated method stub
        attributes.add(attbute);
    }

    @Override
    public void showAttributes() {
        // TODO Auto-generated method stub
        for (String attribute : attributes) {
            System.out.println(attribute);
        }
    }

}

定义生产流程规范,如起名字、刷颜色、输出产品等……

package com.designpattern.builder;

public interface ProcedureRule {

    public void setName();

    public void setColor();

    public Product getproduct();
}

员工为具体的创建者,需要按产品的生产流程生产产品

package com.designpattern.builder;

public class EmployeeForPen implements ProcedureRule {
    private Product product = new Pen();
    @Override
    public void setName() {
        // TODO Auto-generated method stub
        product.createProductAttributes("set Name");
    }

    @Override
    public void setColor() {
        // TODO Auto-generated method stub
        product.createProductAttributes("set Color");
    }

    @Override
    public Product getproduct() {
        // TODO Auto-generated method stub
        return product;
    }
}
package com.designpattern.builder;

public class EmployeeForCup implements ProcedureRule {
    private Product product = new Cup();
    @Override
    public void setName() {
        // TODO Auto-generated method stub
        product.createProductAttributes("cup set Name");
    }

    @Override
    public void setColor() {
        // TODO Auto-generated method stub
        product.createProductAttributes("cup set Color");
    }

    @Override
    public Product getproduct() {
        // TODO Auto-generated method stub
        return product;
    }
}

指挥类:主管告诉员工生产产品

package com.designpattern.builder;

public class Master {

    private ProcedureRule procedureRule = null;

    public Master(ProcedureRule procedureRule) {
        // TODO Auto-generated constructor stub
        this.procedureRule = procedureRule;
    }

    public Product build() {
        procedureRule.setName();
        procedureRule.setColor();
        return procedureRule.getproduct();
    }
}

客户端:客户与主管洽谈业务,下订单需要钢笔、需要杯子

package com.designpattern.builder;

public class TestMain {
    public static void main(String[] args) {
        Master master = new Master(new EmployeeForPen());
        Product product = master.build();
        product.showAttributes();

        master = new Master(new EmployeeForCup());
        product = master.build();
        product.showAttributes();
    }
}

另外一个例子:
通常在多属性类中,构造函数有多种组合,此时可能需要写很多构造函数,满足各种属性组合,通常的做法是多个构造函数调用一个统一的构造函数,实在不行就写多个,如

public class Product {

    private String name;
    private String type;
    private String price;
    private String color;
    private String size;

    public Product(String name, String type, String price, String color, String size) {
        super();
        this.name = name;
        this.type = type;
        this.price = price;
        this.color = color;
        this.size = size;
    }

    public Product(String name, String type, String price, String color) {
        new Product(name, type, price, color, "");
    }

    public Product(String name, String type, String price) {
        new Product(name, type, price, "", "");
    }

    public Product(String name, String type) {
        new Product(name, type, "", "", "");
    }

    public Product(String name) {
        new Product(name, "", "", "", "");
    }
    //省略了其他的组合情况~
}

这种一定程度上省略了一部分代码,代码量还是很多。看如何用创建者模式解决该问题(省略了指挥类)

package com.designpattern.builder2;

public class Product {

    private String name;
    private String type;
    private String price;
    private String color;
    private String size;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public Product(String name, String type, String price, String color, String size) {
        super();
        this.name = name;
        this.type = type;
        this.price = price;
        this.color = color;
        this.size = size;
    }
}
package com.designpattern.builder2;

public class Builder {
    private String builder_name;
    private String builder_type;
    private String builder_price;
    private String builder_color;
    private String builder_size;

    public Builder setName(String name) {
        this.builder_name = name;
        return this;
    }
    public Builder setType(String type) {
        this.builder_type = type;
        return this;
    }
    public Builder setPrice(String price) {
        this.builder_price = price;
        return this;
    }
    public Builder setColor(String color) {
        this.builder_color = color;
        return this;
    }
    public Builder setSize(String size) {
        this.builder_size = size;
        return this;
    }

    public Product build() {
        return new Product(builder_name, builder_type, builder_price, builder_color, builder_size);
    }

}
package com.designpattern.builder2;

public class TestMain {

    public static void main(String[] args) {
        Product product=new Builder().setColor("color").setName("name").build();
        System.err.println(product.getColor());
        System.err.println(product.getName());
        System.err.println(product.getPrice());
    }
}
color
name
null

补充上指挥者

package com.designpattern.builder2;


public class Master {
    private Builder builder = null;

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

    public Product build() {
        builder.setColor("Master set color");
        builder.setName("Master set name");
        return builder.build();
    }
}

修改测试主类为

package com.designpattern.builder2;

public class TestMain {

    public static void main(String[] args) {
        //测试省略指挥类
        Product product=new Builder().setColor("color").setName("name").build();
        System.err.println(product.getColor());
        System.err.println(product.getName());
        System.err.println(product.getPrice());

        //测试带指挥类
        Builder builder = new Builder();
        Master master = new Master(builder);
        product=master.build();
        System.err.println(product.getColor());
        System.err.println(product.getName());
        System.err.println(product.getPrice());
    }
}