引言

解决结构复杂对象的创建问题。

一个复杂对象,有着很多种状态。创建一个复杂对象,不仅需要创建初始状态,可能还要创建中间状态等等。针对创建初始状态,用构造函数即可(new一个对象即可);但new不能满足构造中间状态。

原型模式的代码

  1. Prototype.cpp

    1. //抽象类
    2. class ISplitter{
    3. public:
    4. virtual void split()=0;
    5. virtual ISplitter* clone()=0; //通过克隆自己来创建对象
    6. virtual ~ISplitter(){}
    7. };
  2. ConcretePrototype.cpp ```cpp //具体类 class BinarySplitter : public ISplitter{ public: virtual ISplitter* clone(){

    1. return new BinarySplitter(*this); //通过拷贝构造函数,深度拷贝自己
    2. //前提是类的拷贝构造函数要写正确,要写成深度拷贝

    } };

class TxtSplitter: public ISplitter{ public: virtual ISplitter clone(){ return new TxtSplitter(this); } };

class PictureSplitter: public ISplitter{ public: virtual ISplitter clone(){ return new PictureSplitter(this); } };

class VideoSplitter: public ISplitter{ public: virtual ISplitter clone(){ return new VideoSplitter(this); } };

  1. 3. 客户端Client.cpp
  2. ```cpp
  3. class MainForm : public Form
  4. {
  5. ISplitter* prototype;//原型对象
  6. public:
  7. MainForm(ISplitter* prototype){
  8. this->prototype=prototype;
  9. }
  10. void Button1_Click(){
  11. //直接调用可以吗?
  12. //prototype->split();
  13. //不行!原型对象是供我们克隆用的,不能直接使用,否则就违背了原型设计模型的宗旨
  14. //真正使用是需要创建一个新的对象
  15. ISplitter * splitter= prototype->clone(); //克隆原型
  16. splitter->split(); //再使用
  17. delete splitter;
  18. }
  19. };

动机

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口

如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易用对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

[2021/3/7理解] 其实就是我们想获得对象a的克隆体,而new出来的对象是默认状态,和a的状态不同(结构复杂就在这里体现),所以需要根据对象a来克隆一份。a就称之为原型

【工厂方法模式 与 原型模式 相比】

  1. 原型创建对象的方式,比工厂方法的灵活性更大。工厂方法只能创建初始状态的对象,而原型模式既可创建初始状态的对象,也可拷贝任意状态的对象
  2. 如何选择?
    1. 简单来说,如果只要几步简单的步骤就能创建一个新对象,那么用工厂方法
    2. 如果你要考虑对象非常复杂的中间状态,而且希望保留那个中间状态。那么用原型

      原型设计模式的定义

      使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。——《设计模式》GoF

结构

image.png

要点总结

要点一:Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。

要点二:Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方clone

要点三:Prototype模式中的Clone方法可以利用某些框架中的序列化来实现深拷贝

  1. 在某些语言中,如Java、C#,它们的深克隆和C++不一样,简单来讲,它们没有拷贝构造函数,它们可以通过序列化的方式实现深拷贝(在内存中先做一个序列化,再做一个反序列化)
  2. 在C++中,做序列化不是这么容易的,需要很多框架的搭配。但C++有一个便利的条件(拷贝构造函数),所以用拷贝构造函数来做Prototype模式比较方便