C++设计模式——原型 (克隆)模式

一、什么是原型模式

Prototype模式说简单点,就是提供了一个clone, 通过已存在对象进行新对象创建。clone()实现和具体的实现语言相关,在C++中我们通过拷贝构造函数实现。

那为啥要写clone的接口来实现这个目的呢?直接使用拷贝构造不香么,偶然在知乎中看到陈硕大佬对此的一个回答,觉得豁然开朗。

Prototype 的意义在于,你拿到一个 基类指针 Base* ,它指向某个 派生类 Derived 对象,你想克隆出 Derived对象,但代码中不写出 Derived 的具体类型,因为有很多派生类,这种情况下你用构造函数是搞不定的。type-switch 是 bad smells 。另外,这里考虑 virtual 的性能损失是主次不分,构造对象需要分配内存,这开销比一次虚函数调用大多了。

--陈硕在知乎中的回答

二、代码示例

cpp 复制代码
#include <iostream>
#include <memory>
#include <cassert>
using namespace std;

class Prototype
{
public:

	/// 这里引入NVI模式
    std::unique_ptr<Prototype> clone(){ return clone_impl();}

    void noloop() const{ return noloop_impl();}

private:
    virtual std::unique_ptr<Prototype> clone_impl() const = 0;
    virtual void noloop_impl() const = 0;
public:
    Prototype() = default;
    virtual ~Prototype() = default;
protected:
    Prototype(const Prototype&) = default;
    Prototype(Prototype&&) = default;
    Prototype& operator =(const Prototype&) = default;
    Prototype& operator=(Prototype&&) = default;
};

class Derived : public Prototype
{
private:
    /// 本质实现还是通过拷贝构造函数,在本例中默认是浅拷贝
    std::unique_ptr<Prototype> clone_impl() const
    {
        return std::make_unique<Derived>(*this);
    }

    void noloop_impl() const{ cout << __FUNCTION__ << endl;}
};



int main()
{

    std::unique_ptr<Prototype> p0 = std::make_unique<Derived>();
    std::unique_ptr<Prototype> p1 = p0->clone();
    p1->noloop();

    assert((typeid(*p0) == typeid(*p1)) && (typeid(*p1) == typeid(Derived)));
    
    /// 从结果可以看出,p0和p1指向的均为Derived类型对象

    return 0;
}

三、总结

Prototype 模式的结构和实现都很简单,其关键就是(C++中)拷贝构造函数 的实现方

式,这也是C++实现技术层面上的事情。由于在示例代码中不涉及到深层拷贝(主要指有指针、复合对象的情况),因此我们通过编译器提供的默认的拷贝构造函数(按位拷贝)的方式进行实现。说明的是这一切只是为了实现简单起见,也因为本篇的重点不在拷贝构造函数的实现技术,而在Prototype模式本身的思想。

Prototype 模式通过复制原型(Prototype)而获得新对象创建的功能,这里Prototype本身就是"对象工厂"(因为能够生产对象),实际上Prototype 模式和Builder 模式、AbstractFactory 模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder 模式重点在对复杂对象的一步步创建(并不直接返回对象),AbstractFactory 模式重在产生多个相互依赖类的对象,而Prototype模式重在从自身复制自己创建新类。

相关推荐
扶尔魔ocy36 分钟前
【QT入门到晋级】用开源的自定义控件开发
c++·qt·自定义控件
akinggw2 小时前
libsherpacore - 基于 sherpa-onnx 的 C++ 语音交互静态库
c++·交互·语音识别
xiaoye-duck2 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt
東隅已逝,桑榆非晚3 小时前
算法3.双指针法-快乐数
c++·笔记·学习·算法
eggwyw3 小时前
C++相交链表和反转链表详解
开发语言·c++
杜 硕3 小时前
从零开始的C++生活——第六讲——02
c++·算法·生活
工一木子3 小时前
设计模式与生活⑩:地铁没变,你换了个状态
设计模式
小超人诞生日记4 小时前
C++ STL 反向迭代器:从源码框架到适配器实现
c++·算法
青少儿编程课堂4 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园成语接龙大挑战解析
c++·python·算法·bfs·信息学竞赛
小贾要学习4 小时前
【C++后端开发项目】Reactor 模型 / C++ 仿写 muduo HTTP 服务器:让底层网络库真正跑起网页
linux·服务器·c++·http·网络编程·muduo·reactor模型