From 751033f2e903b2e74726fe1620bf8b224eb49f62 Mon Sep 17 00:00:00 2001 From: Yuki Date: Sun, 6 Apr 2025 00:42:29 +0800 Subject: [PATCH] feat: Prototype Implemented a demo for the Prototype. --- 06_prototype.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ notes.md | 6 +++++ 2 files changed, 68 insertions(+) create mode 100644 06_prototype.cpp diff --git a/06_prototype.cpp b/06_prototype.cpp new file mode 100644 index 0000000..3f9d5d0 --- /dev/null +++ b/06_prototype.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +using namespace std; + +class Shape { +public: + virtual shared_ptr 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 clone() override { + // Default copy using the copy constructor. + // You can customize this to perform deep or shallow copy as needed. + return std::make_shared(*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 clone() override { + return std::make_shared(*this); + } + + virtual void draw() override { + cout << "draw " << x1 << " " << y1 << " " << x2 << " " << y2 << endl; + } +}; + +int main() { + shared_ptr c = make_shared(1, 2, 3); + shared_ptr s = make_shared(1, 2, 3, 4); + + vector> origin_shapes = {c, s}; + vector> 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(); + } +} diff --git a/notes.md b/notes.md index 6dc4958..96d4f21 100644 --- a/notes.md +++ b/notes.md @@ -33,3 +33,9 @@ 单例模式是一种解决方案,这个类只通过静态的 `get_instance()` 提供统一访问方式,并且不提供拷贝构造和赋值操作。这样多个依赖的全局变量可以在这个类里管理。此外测试时可以只改内部实现,对外接口不变,提高了可维护性与可测试性。 具体实现上有一些技巧。为了只创建一次,可以用 `get_instance()` 中使用 `static` 变量(懒汉式),也可以这个类有一个 `static` 类成员(饿汉式),还可以用 `static` 指针成员,对于指针为空时(第一次访问)额外做初始化(需要注意创建时的线程安全,比如双检查)。 + +## 原型模式(Prototype Pattern) + +有时需要在项目中创建副本,那么如何创建重复对象?很容易想到使用复制或赋值操作符,而不是普通的构造函数。但是这些方法没有多态性,如果很多子类需要复制就会有点麻烦。 + +解决方案也很简单,父类提供一种 `clone` 方法。这样客户端只需要调用 `clone` 方法,不需要知道这个类具体是什么。这种方法常配合对象注册表使用,通过维护一个原型缓存容器(如`map`),根据名字/类型复制对象。