当前位置: 首页> 文旅> 旅游 > 设计模式之原型设计模式

设计模式之原型设计模式

时间:2025/7/10 2:15:19来源:https://blog.csdn.net/qq_74811378/article/details/141787510 浏览次数:0次

一、原型设计模式概念

原型模式(Prototype)是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。

原型模式主要用于对象的复制,它的核心是就是类图中的原型类 Prototype。Prototype 类需要具备以下两个条件:

  • 实现 Cloneable 接口。在 java 语言有一个 Cloneable 接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用 clone 方法。在 java 虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出 CloneNotSupportedException 异常。
  • 重写 Object 类中的 clone 方法。Java 中,所有类的父类都是 Object 类,Object 类中有一个 clone 方法,作用是返回对象的一个拷贝,但是其作用域 protected 类型的,一般的类无法调用,因此,Prototype 类需要将 clone 方法的作用域修改为 public 类型。
我们复习一下C++中的浅拷贝与深拷贝:

浅拷贝是指当对象的字段值被复制时,字段引用的对象不会被复制。

例如:如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那麽两个对象将引用同一个字符串。

深拷贝是指当一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝。

适用场景

  • 如果你需要复制一些对象, 同时又希望代码独立于这些对象所属的具体类, 可以使用原型模式。
  • 如果子类的区别仅在于其对象的初始化方式, 那么你可以使用该模式来减少子类的数量。 别人创建这些子类的目的可能是为了创建特定类型的对象

原型设计模式的结构

  1. 原型 (Prototype) 接口将对克隆方法进行声明。 在绝大多数情况下, 其中只会有一个名为 clone克隆的方法。
  2. 具体原型 (Concrete Prototype) 类将实现克隆方法。 除了将原始对象的数据复制到克隆体中之外, 该方法有时还需处理克隆过程中的极端情况, 例如克隆关联对象和梳理递归依赖等等。
  3. 客户端 (Client) 可以复制实现了原型接口的任何对象
  4. 克隆形状:生成完全相同的几何对象副本,同时无需代码与对象所属类耦合。

代码及类图如下:

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

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

#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
using namespace std;
enum Type
{ROBOT_CAT = 0, ROBOT_DOG
};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;
};
class RobotCat :public Robot
{
protected: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;cout << "Cat charge is " << m_prototype_name << " " << m_stateOfCharge << " " << m_CatValue << endl;}};class RobotDog :public Robot
{
protected: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;cout << "Dog charge is " << m_prototype_name << " " << m_stateOfCharge << " " << m_DogValue << endl;}};class CloneFactory
{
public:unordered_map<Type, Robot*> m_prototypes;CloneFactory(){m_prototypes[ROBOT_CAT] = new RobotCat("Cat", 1.0);m_prototypes[ROBOT_DOG] = new RobotDog("Dog", 2.0);}~CloneFactory(){delete m_prototypes[ROBOT_CAT];delete m_prototypes[ROBOT_DOG];}Robot* createRobot(Type type){return m_prototypes[type]->clone();}
};
void clintcode(CloneFactory& factory)
{cout<<"Cat Clone:" << endl;Robot* robot1 = factory.createRobot(ROBOT_CAT);robot1->setStateOfCharge(0.5);delete robot1;Robot* robot3 = factory.createRobot(ROBOT_CAT);robot3->setStateOfCharge(0.6);delete robot3;cout << "Dog Clone:" << endl;Robot* robot2 = factory.createRobot(ROBOT_DOG);robot2->setStateOfCharge(0.5);delete robot2;
}int main()
{CloneFactory factory;clintcode(factory);return 0;
}

二、原型设计模式的优缺点

1 . 原型模式优点 : 性能高 , 简单 ;
        ① 性能高 : 使用原型模式复用的方式创建实例对象 , 比使用构造函数重新创建对象性能要高 ; ( 针对类实例对象开销大的情况 )

        ② 流程简单 : 原型模式可以简化创建的过程 , 可以直接修改现有的对象实例的值 , 达到复用的目的 ; ( 针对构造函数繁琐的情况 )

2 . 原型模式缺点 : 实现复杂 , 坑多 ;
        ① 覆盖 clone 方法 ( 必须 ) : 必须重写对象的 clone 方法 , Java 中提供了 cloneable 标识该对象可以被拷贝 , 但是必须覆盖 Object 的 clone 方法才能被拷贝 ;

        ② 深拷贝 与 浅拷贝 风险 : 克隆对象时进行的一些修改 , 容易出错 ; 需要灵活运用深拷贝与浅拷贝操作 ;

关键字:设计模式之原型设计模式

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: