feat: Prototype
Implemented a demo for the Prototype.
This commit is contained in:
parent
f7eac92f68
commit
751033f2e9
62
06_prototype.cpp
Normal file
62
06_prototype.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Shape {
|
||||||
|
public:
|
||||||
|
virtual shared_ptr<Shape> clone() = 0;
|
||||||
|
virtual void draw() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circle : public Shape {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int r;
|
||||||
|
public:
|
||||||
|
Circle(int x, int y, int r): x(x), y(y), r(r) {}
|
||||||
|
|
||||||
|
virtual shared_ptr<Shape> clone() override {
|
||||||
|
// Default copy using the copy constructor.
|
||||||
|
// You can customize this to perform deep or shallow copy as needed.
|
||||||
|
return std::make_shared<Circle>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void draw() override {
|
||||||
|
cout << "draw " << x << " " << y << " " << r << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Square : public Shape {
|
||||||
|
int x1;
|
||||||
|
int y1;
|
||||||
|
int x2;
|
||||||
|
int y2;
|
||||||
|
public:
|
||||||
|
Square(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {}
|
||||||
|
|
||||||
|
virtual shared_ptr<Shape> clone() override {
|
||||||
|
return std::make_shared<Square>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void draw() override {
|
||||||
|
cout << "draw " << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
shared_ptr<Shape> c = make_shared<Circle>(1, 2, 3);
|
||||||
|
shared_ptr<Shape> s = make_shared<Square>(1, 2, 3, 4);
|
||||||
|
|
||||||
|
vector<shared_ptr<Shape>> origin_shapes = {c, s};
|
||||||
|
vector<shared_ptr<Shape>> clone_shapes;
|
||||||
|
for (auto shape : origin_shapes) {
|
||||||
|
// You can clone without knowing the concrete type of shape.
|
||||||
|
clone_shapes.push_back(shape->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto shape : clone_shapes) {
|
||||||
|
shape->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
notes.md
6
notes.md
@ -33,3 +33,9 @@
|
|||||||
单例模式是一种解决方案,这个类只通过静态的 `get_instance()` 提供统一访问方式,并且不提供拷贝构造和赋值操作。这样多个依赖的全局变量可以在这个类里管理。此外测试时可以只改内部实现,对外接口不变,提高了可维护性与可测试性。
|
单例模式是一种解决方案,这个类只通过静态的 `get_instance()` 提供统一访问方式,并且不提供拷贝构造和赋值操作。这样多个依赖的全局变量可以在这个类里管理。此外测试时可以只改内部实现,对外接口不变,提高了可维护性与可测试性。
|
||||||
|
|
||||||
具体实现上有一些技巧。为了只创建一次,可以用 `get_instance()` 中使用 `static` 变量(懒汉式),也可以这个类有一个 `static` 类成员(饿汉式),还可以用 `static` 指针成员,对于指针为空时(第一次访问)额外做初始化(需要注意创建时的线程安全,比如双检查)。
|
具体实现上有一些技巧。为了只创建一次,可以用 `get_instance()` 中使用 `static` 变量(懒汉式),也可以这个类有一个 `static` 类成员(饿汉式),还可以用 `static` 指针成员,对于指针为空时(第一次访问)额外做初始化(需要注意创建时的线程安全,比如双检查)。
|
||||||
|
|
||||||
|
## 原型模式(Prototype Pattern)
|
||||||
|
|
||||||
|
有时需要在项目中创建副本,那么如何创建重复对象?很容易想到使用复制或赋值操作符,而不是普通的构造函数。但是这些方法没有多态性,如果很多子类需要复制就会有点麻烦。
|
||||||
|
|
||||||
|
解决方案也很简单,父类提供一种 `clone` 方法。这样客户端只需要调用 `clone` 方法,不需要知道这个类具体是什么。这种方法常配合对象注册表使用,通过维护一个原型缓存容器(如`map<string, Prototype*>`),根据名字/类型复制对象。
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user