生成器/建造者模式——创建型模式
什么是生成器模式?
生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。
提炼两个关键点:Ⅰ.分步骤创建复杂对象。Ⅱ.相同创建代码创建不同类型和形式的对象。
Ⅰ.分步骤创建复杂对象:
假设有一个产品类,这个产品有100个非静态成员属性,为了保证程序的健壮性,我们要在构造函数中对这100个属性进行init。此时构造函数"又大又长"不说,我们在调用时还要逐一去找准参数顺序,并且如果想设置一些默认值,还要去重载构造函数设置缺省参数,真的是极其复杂。
生成器模式就是把创建的行为抽象出来,抽象出两个类,分别是生成器(builder)和主管(director)。
生成器(builder):生成器类中依赖于某个产品(产品加工器),内部包含一个产品实体,并实现了"一堆"set方法用于设置产品属性字段,并对外**提供getproduct()
**方法。
主管(director): 主管类中实现的是产品的参数设置方法(相当于人拿着产品参数说明书)。主管有很多说明书(idea),面对同一个生成器,设置参数不同,构造出的产品就不同。也就是说操作生成器的动作在主管类的成员方法中。
总结:在CodeClient中,我们只需要定义一个生成器和一个主管,就可以根据主管的不同想法操作同一个生成器生成不同参数的产品。又因为对每个字段设置的操作都实现成独立的方法,所以我们需要考虑设置顺序,需要哪个调用哪个即可。
Ⅱ.相同创建代码创建不同类型和形式的对象:
简单来说,主管的某一个想法,可以作用到不同的生成器上。比如说主管类根据自己的产品参数说明书操作汽车生成器,来生成一台汽车。那同样可以用这个产品参数说明书操作汽车手册生成器,生成一个汽车手册对象。因为对于手册和汽车实体,字段几何都是一样的,比如说几个座位、几个门、是否有GPS…,只不过字段类型可能不同。
用C++实现一个例子:
/*************************************************************************> File Name: builder.cpp> Author:> Mail:> Created Time: Tue Mar 12 10:54:06 2024************************************************************************/#include <iostream>
#include <cstring>
using namespace std;class Car {
public:int seatnum;int doornum;bool GPS;
};class Manual {
public:string seatnum;string doornum;string GPS;
};class Builder {
public:virtual void setSeats(int) = 0;virtual void setDoors(int) = 0;virtual void setGPS(bool) = 0;
};class CarBuilder : public Builder {
private:Car car;
public:void setSeats(int num) override {car.seatnum = num;}void setDoors(int num) override {car.doornum = num;}void setGPS(bool is) override {car.GPS = is;}Car getCarIns() {return car;}
};class ManualBuilder : public Builder {
private:Manual manual;
public:void setSeats(int num) override {manual.seatnum = "This car has " + to_string(num) + " seat.";}void setDoors(int num) override {manual.doornum = "This car has " + to_string(num) + " door.";}void setGPS(bool is) override {if (is) manual.GPS = "Support GPS";else manual.GPS = "No support GPS";}Manual getManualIns() {return manual;}
};class Director {
public:void makeSUV(Builder &builder) {builder.setSeats(4);builder.setDoors(4);builder.setGPS(true);}void makeSports(Builder &builder) {builder.setSeats(2);builder.setDoors(2);builder.setGPS(false);}
};void CodeClient() {Director director;CarBuilder carbuilder;director.makeSUV(carbuilder);Car car = carbuilder.getCarIns();cout << car.seatnum << endl << car.doornum << endl << car.GPS << endl;ManualBuilder manualbuilder;director.makeSports(manualbuilder);Manual manual = manualbuilder.getManualIns();cout << manual.seatnum << endl << manual.doornum << endl << manual.GPS << endl;return ;
}int main() {CodeClient();return 0;
}