生成器模式--创建型模式

1、描述

生成器模式也叫着建造者模式(Builder Pattern)是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。

优点:封装性--使用建造者模式可以使客户端不必知道产品内部组成的细节;建造者独立,容易扩展;便于控制细节风险--由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

2、结构图

  • 生成器(Builder)接口声明在所有类型生成器中通用的产品构造步骤
  • 具体生成器(ConcreateBuilder)提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
  • 产品(Product)是最终生成的对象。由不同生成器构造的产品无需属于同一类层次结构或接口
  • 主管(Director)类定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置。

3、C++代码

#include <string>
#include <vector>
#include <iostream>

// 只有当产品较为复杂且需要详细配置时,使用生成器模式才有意义
//不像其他的创建型模式,不同的具体构造者可以生产不相关的产品,
//换句话说,不同的构造者的产品可能不总是遵循相同的接口
class Product1{
    public:
    std::vector<std::string> parts_;
    void ListParts()const{
        std::cout << "Product parts: ";
        for (size_t i=0;i<parts_.size();i++){
            if(parts_[i]== parts_.back()){
                std::cout << parts_[i];
            }else{
                std::cout << parts_[i] << ", ";
            }
        }
        std::cout << "\n\n"; 
    }
};


// 生成器接口声明了创建产品对象不同部件的方法。
class Builder{
    public:
    virtual ~Builder(){}
    virtual void ProducePartA() const =0;
    virtual void ProducePartB() const =0;
    virtual void ProducePartC() const =0;
};

// 具体生成器类将遵循生成器接口并提供生成步骤的具体实现。你的程序中可能会
// 有多个以不同方式实现的生成器变体。
class ConcreteBuilder1 : public Builder{
    private:

    Product1* product;

    // 一个新的生成器实例必须包含一个在后续组装过程中使用的空产品对象。
    public:

    ConcreteBuilder1(){
        this->Reset();
    }

    ~ConcreteBuilder1(){
        delete product;
    }

    void Reset(){
        this->product= new Product1();
    }

    // 所有生成步骤都会与同一个产品实例进行交互。
    void ProducePartA()const override{
        this->product->parts_.push_back("PartA1");
    }

    void ProducePartB()const override{
        this->product->parts_.push_back("PartB1");
    }

    void ProducePartC()const override{
        this->product->parts_.push_back("PartC1");
    }

    // 具体生成器需要自行提供获取结果的方法。这是因为不同类型的生成器可能
    // 会创建不遵循相同接口的、完全不同的产品。所以也就无法在生成器接口中
    // 声明这些方法(至少在静态类型的编程语言中是这样的)。
    //
    // 通常在生成器实例将结果返回给客户端后,它们应该做好生成另一个产品的
    // 准备。因此生成器实例通常会在 `getProduct(获取产品)`方法主体末尾
    // 调用重置方法。但是该行为并不是必需的,你也可让生成器等待客户端明确
    // 调用重置方法后再去处理之前的结果。

    // 最好使用智能指针,避免内存泄露

    Product1* GetProduct() {
        Product1* result= this->product;
        this->Reset();
        return result;
    }
};

// 主管(指导类)只负责按照特定顺序执行生成步骤。其在根据特定步骤或配置来生成产品时
// 会很有帮助。由于客户端可以直接控制生成器,所以严格意义上来说,主管类并
// 不是必需的。
class Director{

    private:
    Builder* builder;

    // 主管可同由客户端代码传递给自身的任何生成器实例进行交互。客户端可通
    // 过这种方式改变最新组装完毕的产品的最终类型。
    public:

    void set_builder(Builder* builder){
        this->builder=builder;
    }

    // 主管可使用同样的生成步骤创建多个产品变体。
    void BuildMinimalViableProduct(){
        this->builder->ProducePartA();
    }
    
    void BuildFullFeaturedProduct(){
        this->builder->ProducePartA();
        this->builder->ProducePartB();
        this->builder->ProducePartC();
    }
};

// 客户端代码会创建生成器对象并将其传递给主管,然后执行构造过程。最终结果
// 将需要从生成器对象中获取。
void ClientCode(Director& director)
{
    ConcreteBuilder1* builder = new ConcreteBuilder1();
    director.set_builder(builder);
    std::cout << "Standard basic product:\n"; 
    director.BuildMinimalViableProduct();
    
    Product1* p= builder->GetProduct();
    p->ListParts();
    delete p;

    std::cout << "Standard full featured product:\n"; 
    director.BuildFullFeaturedProduct();

    p= builder->GetProduct();
    p->ListParts();
    delete p;

    //记住,生成器模式可以不使用主管类
    std::cout << "Custom product:\n";
    builder->ProducePartA();
    builder->ProducePartC();
    p=builder->GetProduct();
    p->ListParts();
    delete p;

    delete builder;
}

int main(){
    Director* director= new Director();
    ClientCode(*director);
    delete director;
    return 0;    
}

参考

https://refactoringguru.cn/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值