设计模式(四) --- 原型模式

设计模式 — 原型模式

原型模式是一种创建型设计模式,它允许你在不指定具体类的情况下创建新的对象。通过克隆一个现有的对象来创建新的对象,而不是通过常规的构造函数。这样可以简化对象的创建过程,尤其是在对象的创建过程比较复杂时。
在c++中,实现原型模式一般可以有两种方式实现,第一种方法是编写正确的拷贝原始对象的代码,比如,拷贝工作可以在拷贝构造赋值运算符或者在单独的类成员函数中实现,第二种方法是编写序列化/反序列化的代码,比如利用boost.serialization的库在完成序列化后立即进行反序列化,由此完成复制拷贝工作。
以下,我们将使用类成员方法的方式分别演示“拷贝原始对象”&“序列化/反序列化”这两种主要途径实现原型模式。

1. 编写拷贝原始对象的方式

1.1 定义原型接口

#include <iostream>
#include <memory>

class Prototype {
public:
    virtual ~Prototype() = default;
    virtual std::shared_ptr<Prototype> clone() const = 0;
};

1.2 定义具体原型类

class ConcretePrototype1 : public Prototype {
public:
    ConcretePrototype1(int value) : value(value) {}

    std::shared_ptr<Prototype> clone() const override {
        // 使用拷贝构造函数克隆对象
        // 具体类的成员可在其构造中初始化,也可在clone方法中初始化或者赋值
        return std::make_shared<ConcretePrototype1>(*this);
    }

    void printValue() const {
        std::cout << "ConcretePrototype1 value: " << value << std::endl;
    }

private:
    int value;
};

class ConcretePrototype2 : public Prototype {
public:
    ConcretePrototype2(double value) : value(value) {}

    std::shared_ptr<Prototype> clone() const override {
        // 使用拷贝构造函数克隆对象
        // 具体类的成员可在其构造中初始化,也可在clone方法中初始化或者赋值
        return std::make_shared<ConcretePrototype2>(*this);
    }

    void printValue() const {
        std::cout << "ConcretePrototype2 value: " << value << std::endl;
    }

private:
    double value;
};

1.3 客户端(调用方)

int main() {
    // 创建具体原型对象
    // 创建时可传入自定义列表初始化类成员
    auto prototype1 = std::make_shared<ConcretePrototype1>(10);
    auto prototype2 = std::make_shared<ConcretePrototype2>(20.5);

    // 克隆原型对象
    auto clonedPrototype1 = prototype1->clone();
    auto clonedPrototype2 = prototype2->clone();

    // 打印克隆对象的值
    clonedPrototype1->printValue();
    clonedPrototype2->printValue();

    return 0;
}

2. 使用序列化/反序列化

2.1 定义原型接口

#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class Prototype {
public:
    virtual ~Prototype() = default;
    virtual std::shared_ptr<Prototype> clone() const = 0;
};

2.2 定义具体原型类

class ConcretePrototype1 : public Prototype {
public:
    ConcretePrototype1(int value) : value(value) {}

    std::shared_ptr<Prototype> clone() const override {
        // 使用序列化/反序列化克隆对象
        std::ostringstream archiveStream;
        boost::archive::text_oarchive outputArchive(archiveStream);
        outputArchive << *this;

        std::istringstream archiveStreamCopy(archiveStream.str());
        boost::archive::text_iarchive inputArchive(archiveStreamCopy);
        std::shared_ptr<ConcretePrototype1> clonedObject(new ConcretePrototype1());
        inputArchive >> *clonedObject;

        return std::shared_ptr<Prototype>(clonedObject);
    }

    void printValue() const {
        std::cout << "ConcretePrototype1 value: " << value << std::endl;
    }

private:
    friend class boost::serialization::access;

	/*
    * serialize 是一个模板方法,用于定义如何将对象的成员变量序列化和反序列化,
    * 虽然没有显示调用,但是,boost::serialization 库会自动调用这个方法来
    * 处理对象的序列化和反序列化过程。当你使用 outputArchive << *this; 和 
    * inputArchive >> *clonedObject; 时,boost::serialization 会自动
    * 调用 serialize 方法来处理对象的序列化和反序列化。
    */
    template<class Archive> void serialize(Archive & ar, const unsigned int version) {
        ar & value;
    }

    int value;
};

class ConcretePrototype2 : public Prototype {
public:
    ConcretePrototype2(double value) : value(value) {}

    std::shared_ptr<Prototype> clone() const override {
        // 使用序列化/反序列化克隆对象
        std::ostringstream archiveStream;
        boost::archive::text_oarchive outputArchive(archiveStream);
        outputArchive << *this;

        std::istringstream archiveStreamCopy(archiveStream.str());
        boost::archive::text_iarchive inputArchive(archiveStreamCopy);
        std::shared_ptr<ConcretePrototype2> clonedObject(new ConcretePrototype2());
        inputArchive >> *clonedObject;

        return std::shared_ptr<Prototype>(clonedObject);
    }

    void printValue() const {
        std::cout << "ConcretePrototype2 value: " << value << std::endl;
    }

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & value;
    }

    double value;
};

2.3 客户端代码

客户端调用代码示例同“1.3”中所示,此处略!

总之:原型模式通过克隆一个现有的对象来创建新的对象,适用于对象创建过程复杂或需要创建多个相似对象的场景。在 C++ 中,可以通过编写拷贝构造函数和赋值操作符来实现克隆,也可以通过序列化/反序列化来实现克隆。每种方法都有其优缺点,选择哪种方法取决于具体的应用场景和需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值