建造者设计模式学习
1.介绍
建造者模式是一种创建型设计模式,它将一个复杂对象的构建过程与它的表示分离,使得相同的构建过程可以创建不同的表示。通过分步骤地构建对象,建造者模式提供了更细粒度的控制和灵活性,特别适合需要灵活创建复杂对象的场景。
- Builder(建造者接口):定义创建对象不同部分的抽象接口。
- ConcreteBuilder(具体建造者):实现 Builder 接口,负责构建复杂对象的各个部分,并最终返回完整对象。
- Director(指挥者):指定复杂对象的构建顺序和步骤,协调 Builder 的调用。【指挥者可以简略】
- Product(产品):由多个部件组成的复杂对象,是建造的最终结果。
2.简单例子
标准的例子:
#include <iostream>
#include <string>
// Product: 复杂对象
class Computer {
private:
std::string CPU;
std::string GPU;
std::string RAM;
std::string Storage;
public:
void setCPU(const std::string& cpu) { CPU = cpu; }
void setGPU(const std::string& gpu) { GPU = gpu; }
void setRAM(const std::string& ram) { RAM = ram; }
void setStorage(const std::string& storage) { Storage = storage; }
void show() const {
std::cout << "Computer Configuration:\n"
<< "CPU: " << CPU << "\n"
<< "GPU: " << GPU << "\n"
<< "RAM: " << RAM << "\n"
<< "Storage: " << Storage << "\n";
}
};
// Builder: 抽象建造者
class ComputerBuilder {
public:
virtual ~ComputerBuilder() = default;
virtual void buildCPU() = 0;
virtual void buildGPU() = 0;
virtual void buildRAM() = 0;
virtual void buildStorage() = 0;
virtual Computer* getResult() = 0;
};
// ConcreteBuilder: 具体建造者
class GamingComputerBuilder : public ComputerBuilder {
private:
Computer* computer;
public:
GamingComputerBuilder() { computer = new Computer(); }
~GamingComputerBuilder() { delete computer; }
void buildCPU() override { computer->setCPU("Intel i9"); }
void buildGPU() override { computer->setGPU("NVIDIA RTX 4090"); }
void buildRAM() override { computer->setRAM("32GB DDR5"); }
void buildStorage() override { computer->setStorage("2TB SSD"); }
Computer* getResult() override {
Computer* result = computer;
computer = nullptr; // 防止重复释放
return result;
}
};
// Director: 指挥者
class Director {
private:
ComputerBuilder* builder;
public:
void setBuilder(ComputerBuilder* b) { builder = b; }
Computer* construct() {
builder->buildCPU();
builder->buildGPU();
builder->buildRAM();
builder->buildStorage();
return builder->getResult();
}
};
// 客户端代码
int main() {
Director director;
GamingComputerBuilder gamingBuilder;
// 设置建造者
director.setBuilder(&gamingBuilder);
// 构建计算机
Computer* gamingComputer = director.construct();
// 显示结果
gamingComputer->show();
delete gamingComputer;
return 0;
}
// 其实director有点死板,它每次都要使用不同的builder,才能创建不同的对象,直接把创建产品的任务交给builder自己也行。
2.1 链式编程
https://zhuanlan.zhihu.com/p/143101326
关键点是builder的函数直接返回产品对象。
// 产品类
public class KFC {
//套餐必点
private String hamburger;
private String chips;
//套餐选点
private String chicken;
private String cola;
private String pizza;
public KFC(String hamburger,String chips){
this.hamburger = hamburger;
this.hamburger = chips;
}
public void setChicken(String chicken) {
this.chicken = chicken;
}
public void setCola(String cola) {
this.cola = cola;
}
public void setPizza(String pizza) {
this.pizza = pizza;
}
};
// 抽象builder
public abstract class Builder {
abstract Builder setChicken();
abstract Builder setCola();
abstract Builder setPizza();
abstract KFC getKFC();
}
// 具体builder
public class ConcreteBuilder extends Builder {
KFC kfc;
public ConcreteBuilder(String hamburger,String chips){
kfc = new KFC(hamburger,chips);
}
@Override
Builder setChicken() {
kfc.setChicken("鸡腿");
return this; // 返回自己,可以链式调用
}
@Override
Builder setCola() {
kfc.setCola("可乐");
return this;
}
@Override
Builder setPizza() {
kfc.setPizza("披萨");
return this;
}
@Override
KFC getKFC() {
return kfc;
}
}
// main函数
public class BTest {
public static void main(String[] args) {
// 实例化一个具体的builder类,通过它返回一个具体对象
KFC kfc = new ConcreteBuilder("汉堡","薯条").setChicken().setCola().getKFC();
}
}
3.项目实例
gRPC通过builder构建server对象,
这里的builder也不是一个抽象建造者,而是一个具体的类,所以它是只有具体建造者和产品类,也可以理解为将director和builder合二为一了,都合到builder里面了。设计模式是可以简化的,不是那么死板的。