工厂方法
应用场景
将要创造的对象的某一属性有特定类型,不能时任意类型,只能让用户选择类型进行生成。
用户可以仅仅通过调用类型对应的函数,便可得到对象。
核心处理方法
- 构造函数声明为受保护的
- 构造不同类型对象对应的生成方法
实现代码
#include<iostream>
#include <memory>
using namespace std;
enum class Material {
brick,
aerated_concrete,
drywall
};
struct Point2D {
int x, y;
Point2D(int xx, int yy) :x(xx), y(yy) {
}
};
class Wall {
Point2D start, end;
int elevation, height;
public:
Wall(Point2D start, Point2D end, int elevation, int height)
:start{ start }, end{ end }, elevation{ elevation }, height{ height } {
}
};
class SolidWall :public Wall {
int width;
Material material;
public: //改为非public时,无法使用make_unique
SolidWall(const Point2D start, const Point2D end, const int elevation,
const int height, const int width, const Material material)
:Wall(start, end, elevation, height), width{ width }, material{material}
{
}
public:
//以下是三种为工厂方法,强制用户创建特定类型而非任意类型的墙
static SolidWall create_main(Point2D start, Point2D end,
int elevation, int height) {
return SolidWall(start, end, elevation, height, 375, Material::aerated_concrete);
//按值返回
}
static unique_ptr<SolidWall> create_partition(Point2D start, Point2D end,
int elevation, int height) {
return make_unique<SolidWall>(start, end, elevation, height, 120, Material::brick);
//按指针返回
}
static shared_ptr<Wall> create_wall(Point2D start, Point2D end,
int elevation, int height,Material type,int width) {
return make_shared<SolidWall>(start, end, elevation, height, width, type);
//多态形式,只能按指针返回
}
};
int main() {
auto main_wall = SolidWall::create_main({ 0,0 }, { 1,1 },100,200);//调用方法
}
抽象工厂模式
应用场景
可以追踪所有已经创建的对象,通过调用接口时选择属性,便可以返回对应类型的对象
核心处理方法
- 最底层是一个抽象类用来派生。
- 定义不同派生类,分别设置他们的属性
- 设置顶层接口,用来交付给用户调用
代码实现
#include<iostream>
#include <memory>
#include<map>
using namespace std;
//----------------类型定义
struct HotDrink {
virtual void prepare(int volume) = 0;
};
struct Tea:HotDrink
{
void prepare(int volume) override {
cout << "Tea " << endl;
}
};
struct Coffee :HotDrink
{
void prepare(int volume) override {
cout << "Coffee " << endl;
}
};
//----------------
//----------------抽象工厂基类,顾名思义声明为纯虚函数
class HotDrinkFactory {
public: virtual unique_ptr<HotDrink> make() const = 0;
};
//----------------派生各个工厂,各个工厂构造过程不同
class CoffeeFactory:public HotDrinkFactory {
public:
unique_ptr<HotDrink> make() const override {
return make_unique<Coffee>();
}
};
class TeaFactory :public HotDrinkFactory {
public:
unique_ptr<HotDrink> make() const override {
return make_unique<Tea>();
}
};
//----------------定义最高级别接口,选择属性即可生成对象
class DrinkFactory {
map<string, unique_ptr<HotDrinkFactory>> hot_factories;
public:
DrinkFactory() {
hot_factories["coffee"] = make_unique<CoffeeFactory>();
hot_factories["tea"] = make_unique<TeaFactory>();
}
unique_ptr<HotDrink> make_drink(const string& name) {
auto drink = hot_factories[name]->make();
drink->prepare(200);
return drink;
}
};
int main() {
DrinkFactory temp; //顶级接口
auto p1 = temp.make_drink("coffee");
}
工厂模式好处
- 可以知道已经创建的特定类型的对象的数量。
- 可以修改或者完全替换整个对象的创建过程
- 使用智能指针时,则可以通过观察对象的引用次数获得对象全局的引用数量。
- 相比于构造器模式,可以一次创造完整的对象