龙空技术网

设计模式-生成器模式详解

编程少年 16

前言:

目前兄弟们对“创建对象一定会调用构造方法吗为什么”大概比较关切,兄弟们都需要了解一些“创建对象一定会调用构造方法吗为什么”的相关资讯。那么小编也在网络上搜集了一些有关“创建对象一定会调用构造方法吗为什么””的相关资讯,希望姐妹们能喜欢,同学们一起来了解一下吧!

基本介绍

生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中,生成器模式让你能够分步骤创建复杂对象。 生成器不允许其他对象访问正在创建中的产品。

类结构图

类图说明:

生成器(Builder) 接口声明在所有类型生成器中通用的产品构造步骤。具体生成器(Concrete Builder) 提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品。产品(Product) 是最终生成的对象。由不同生成器构造的产品无需属于同一类层次接口或接口。主管(Director) 类定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置。客户端(Client) 必须将某个生成器对象与主管类关联。一般情况下,你只需要通过主管类构造函数的参数进行一次性关联即可。此后主管类就能使用生成器对象完成后续所有的构造任务。但在客户端将生成器对象传递给主管类时还有另一种方式。在这种情况下,你在使用主管类生产产品时每次都可以使用不同的生成器。实现方式清晰地定义通用步骤, 确保它们可以制造所有形式的产品。 否则你将无法进一步实施该模式。在基本生成器接口中声明这些步骤。为每个形式的产品创建具体生成器类, 并实现其构造步骤。不要忘记实现获取构造结果对象的方法。 你不能在生成器接口中声明该方法, 因为不同生成器构造的产品可能没有公共接口, 因此你就不知道该方法返回的对象类型。 但是, 如果所有产品都位于单一类层次中, 你就可以安全地在基本接口中添加获取生成对象的方法。考虑创建主管类。 它可以使用同一生成器对象来封装多种构造产品的方式。客户端代码会同时创建生成器和主管对象。 构造开始前, 客户端必须将生成器对象传递给主管对象。 通常情况下, 客户端只需调用主管类构造函数一次即可。 主管类使用生成器对象完成后续所有制造任务。 还有另一种方式, 那就是客户端可以将生成器对象直接传递给主管类的制造方法。只有在所有产品都遵循相同接口的情况下, 构造结果可以直接通过主管类获取。 否则, 客户端应当通过生成器获取构造结果。适用场景使用生成器模式可避免重叠构造函数(telescopic constructor)的出现

假设你的构造函数中有十个可选参数, 那么调用该函数会非常不方便; 因此, 你需要重载这个构造函数, 新建几个只有较少参数的简化版。 但这些构造函数仍需调用主构造函数, 传递一些默认数值来替代省略掉的参数。

class Pizza {    Pizza(int size) { ... }    Pizza(int size, boolean cheese) { ... }    Pizza(int size, boolean cheese, boolean pepperoni) { ... }    // ...}
当你希望使用代码创建不同形式的产品 (例如石头或木头房屋)时,可使用生成器模式

如果你需要创建的各种形式的产品, 它们的制造过程相似且仅有细节上的差异, 此时可使用生成器模式。基本生成器接口中定义了所有可能的制造步骤, 具体生成器将实现这些步骤来制造特定形式的产品。 同时, 主管类将负责管理制造步骤的顺序。

示例代码产品生成器接口:ProductBuilder

public interface ProductBuilder {    /**     * 创建产品组成部分A     */    void createPartA();    /**     * 创建产品组成部分B     */    void createPartB();    /**     * 创建产品组成部分C     */    void createPartC();    /**     * 获取产品     * @return     */    Product getProduct();}
具体的生成器实现ConcreteBuilder1
public class ConcreteBuilder1 implements ProductBuilder{    private Product product = new Product();    @Override    public void createPartA() {        product.addPart("零件A1");    }    @Override    public void createPartB() {        product.addPart("零件B1");    }    @Override    public void createPartC() {        product.addPart("零件C1");    }    @Override    public Product getProduct() {        return this.product;    }}
ConcreteBuilder2
public class ConcreteBuilder2 implements ProductBuilder{    Product product = new Product();    @Override    public void createPartA() {        product.addPart("零件A2");    }    @Override    public void createPartB() {        product.addPart("零件B2");    }    @Override    public void createPartC() {        product.addPart("零件C2");    }    @Override    public Product getProduct() {        return this.product;    }}
具体的产品:Product
public class Product {    /**产品零件容器**/    private List<String> partList = new ArrayList<>();    /**     * 添加部件     * @param part     */    public void addPart(String part) {        partList.add(part);    }    public void show() {        for(String part:partList) {            System.out.println(part);        }    }}
主管类:ProductBuilderDirector
public class ProductBuilderDirector {    private final ProductBuilder builder;    public ProductBuilderDirector(ProductBuilder builder) {        this.builder = builder;    }    public Product build() {        builder.createPartA();        builder.createPartB();        builder.createPartC();        return builder.getProduct();    }}
客户端调用代码:Client
public class Client {    public static void main(String[] args) {        //构建产品,由A1、B1、C1构成        ProductBuilderDirector builderDirector = new ProductBuilderDirector(new ConcreteBuilder1());        Product product = builderDirector.build();        product.show();        System.out.println("-----------------------------------------");        //构建产品,由A2、B2、C2构成        builderDirector = new ProductBuilderDirector(new ConcreteBuilder2());        product = builderDirector.build();        product.show();    }}

标签: #创建对象一定会调用构造方法吗为什么