4 原型(Protoytpe)模式

原型模式

1.1 分类

(对象)创建型

1.2 提出问题

希望复制一个状态完全相同的对象。首先,新建一个相同类的对象。 然后,复制所有成员变量。 但是,有时候不知道具体类型,而且成员变量可能是私有的。(从外部复制对象并非总是可行的

1.3 解决方案

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。即复制已有对象,而无需使代码依赖他们所属的类。

1.4 实现类图

在这里插入图片描述

  1. 原型(Prototype):接口将对克隆方法进行声明。
  2. 具体原型(Concrete Prototype):类将实现克隆方法。除了将原始对象的数据复制到克隆体中之外,该方法有时还需处理克隆过程中的极端情况,例如克隆关联对象和梳理递归依赖等等。
  3. 客户端(Client):可以复制实现了原型接口的任何对象。

1.5 示例代码

#include <iostream>
#include <unordered_map>
using std::string;

enum Type {
    ROBOT_CAT = 0,
    ROBOT_DOG
};
//原型(Prototype)
class Robot {
protected:
    string m_prototype_name = "";
    float m_stateOfCharge = 0;
public:
    Robot() = default;
    Robot(string name):m_prototype_name(name) {
    }
    virtual ~Robot() {}
    virtual Robot* clone() const = 0;
    virtual void setStateOfCharge(float) = 0;
};
//具体原型(Concrete Prototype)
class RobotCat : public Robot {
private:
    float m_CatValue = 0;
public:
    virtual ~RobotCat() {}
    RobotCat(const RobotCat& robot) {
        m_CatValue = robot.m_CatValue;
    }
    RobotCat(string name, float value) : Robot(name), m_CatValue(value) {
    } 
    virtual Robot* clone() const override {
        return new RobotCat(*this);
    }
    virtual void setStateOfCharge(float value) override {
        m_stateOfCharge = value;
        std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge
            << ",m_CatValue:" << m_CatValue << std::endl;
    }
};
//具体原型(Concrete Prototype)
class RobotDog : public Robot {
private:
    float m_DogValue = 0;
public:
    virtual ~RobotDog() {}
    RobotDog(string name, float value) : Robot(name), m_DogValue(value) {
    }
    virtual Robot* clone() const override {
        return new RobotDog(*this);
    }
    virtual void setStateOfCharge(float value) override {
        m_stateOfCharge = value;
        std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge
            << ",m_DogValue:" << m_DogValue << std::endl;
    }
};
//工厂
class CloneFactory {
    std::unordered_map<Type, Robot*> m_prototypes;
public:
    CloneFactory() {
        m_prototypes[ROBOT_CAT] = new RobotCat("机器猫", 5.0);
        m_prototypes[ROBOT_DOG] = new RobotDog("机器狗", 8.0);
    }
    ~CloneFactory() {
        delete m_prototypes[ROBOT_CAT];
        delete m_prototypes[ROBOT_DOG];
    }
    Robot* createRobot(Type type) {
        return m_prototypes[type]->clone();
    }
};
//客户端
void clintcode(CloneFactory& cloneFactory) {
    std::cout << "克隆机器猫:\n";
    Robot* cloneRobot = cloneFactory.createRobot(ROBOT_CAT);
    cloneRobot->setStateOfCharge(90);
    delete cloneRobot;
    cloneRobot = cloneFactory.createRobot(ROBOT_CAT);
    cloneRobot->setStateOfCharge(80);
    delete cloneRobot;
    std::cout << "克隆机器狗:\n";
    cloneRobot = cloneFactory.createRobot(ROBOT_DOG);
    cloneRobot->setStateOfCharge(75);
    delete cloneRobot;
}
int main()
{
    CloneFactory cloneFactory;
    clintcode(cloneFactory);
}

1.6 举个栗子

克隆形状:生成完全相同的几何对象副本, 同时无需代码与对象所属类耦合。。
在这里插入图片描述

1.7 总结

  1. 可以克隆对象,而无需与它们所属的具体类相耦合。
  2. 可以克隆预生成原型,避免反复运行初始化代码。
  3. 缺点:克隆包含循环引用的复杂对象可能会非常麻烦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值