C++设计模式_10_ Prototype 原型模式(小模式,不太常用)

Prototype 原型模式仍然属于"对象创建模式"模式的一种。前面两篇介绍的工厂方法模式和抽象工厂模式的流行程度要远大于Prototype 原型模式和builder构建器模式,后两种由于较为简单,介绍篇幅也会少一些。

文章目录

  • [1. 动机 (Motivation)](#1. 动机 (Motivation))
  • [2. 代码演示Prototype 原型模式](#2. 代码演示Prototype 原型模式)
    • [2.1 Prototype.cpp](#2.1 Prototype.cpp)
    • [2.2 ConcretePrototype.cpp](#2.2 ConcretePrototype.cpp)
    • [2.3 Client](#2.3 Client)
  • [3. 模式定义](#3. 模式定义)
  • [4. 结构](#4. 结构)
  • [5. 要点总结](#5. 要点总结)
  • [6. 其他参考](#6. 其他参考)

1. 动机 (Motivation)

  • 在软件系统中,经常面临着"某些结构复杂的对象"的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
  • 如何应对这种变化?如何向"客户程序(使用这些对象的程序)"隔离出"这些易变对象"从而使得"依赖这些易变对象的客户程序"不随着需求改变而改变?

与Factory Method工厂方法模式区别就在于"某些结构复杂的对象",利用深克隆将对象你想要的当前状态取出来,原型就可以实现传入的prototype状态是怎样就能深克隆一个出来,实现状态复杂对象的再现。

结构复杂的界定很难明确界定,使用Prototype 原型模式和Factory Method工厂方法模式的区别就是看是否Factory Method工厂方法模式可以很简便的创建对象,还是需要需要考虑对象复杂的中间状态,又希望保留该状态,如果是后者就使用Prototype 原型模式。实际使用原型模式的场景很少。

Prototype 原型模式解决的问题是与Factory Method工厂方法模式一模一样的,也是有一些细微不同,属于Factory Method工厂方法模式的变体。

2. 代码演示Prototype 原型模式

2.1 Prototype.cpp

在C++设计模式_08_Factory Method工厂方法模式中可以看到Factory Method工厂方法对应的代码,Prototype 原型模式中将以下代码中的2个类合并起来。

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};


//工厂基类
class SplitterFactory{
public:
    virtual ISplitter* CreateSplitter()=0;
    virtual ~SplitterFactory(){}
};

变为以下形式:

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
    virtual ISplitter* CreateSplitter()=0;
};

并修改类的名字得到:

Prototype.cpp

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ISplitter* clone()=0; //通过克隆自己来创建对象
    
    virtual ~ISplitter(){}

};

2.2 ConcretePrototype.cpp

Factory Method工厂方法中FileSplitter2.cpp就变为以下形式:

ConcretePrototype.cpp

cpp 复制代码
//具体类
class BinarySplitter : public ISplitter{
public:
    virtual ISplitter* clone(){
        return new BinarySplitter(*this);
    }
};

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);
    }
};

在C++中有着最成熟的克隆自己的方法就是拷贝构造函数,也就是上面的new TxtSplitter(*this),前提是你类的拷贝构造函数要写正确。

2.3 Client

Client也就是MainForm则变为:

cpp 复制代码
class MainForm : public Form
{
    ISplitter*  prototype;//原型对象

public:
    
    MainForm(ISplitter*  prototype){
        this->prototype=prototype;
    }
    
	void Button1_Click(){

		ISplitter * splitter=
            prototype->clone(); //克隆原型得到新对象
        
        splitter->split();
                
	}
};

有些人可能会想到将上面的splitter->split();变为删除 ISplitter * splitter=prototype->clone(); //克隆原型,变为prototype->split();,这是不对的,因为原型对象是供克隆的,真正使用的时候需要创建出新的对象,不能一直使用prototype原型对象。

以上即为Prototype 原型模式。

3. 模式定义

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

------《设计模式》GoF

"原型实例"就是在MainForm中的ISplitter* prototype;,这里的"拷贝"是深克隆。

4. 结构

上图是《设计模式》GoF中定义的Prototype 原型模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分,也就是下图中红框和蓝框框选的部分。

5. 要点总结

  • Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有"稳定的接口"
  • Prototype模式对于"如何创建易变类的实体对象"采用"原型克隆"的方法来做,它使得我们可以非常灵活地动态创建"拥有某些稳定接口"的新对象一-所需工作仅仅是注册一个新类的对象 (即原型),然后在任何需要的地方Clone。
  • Prototype模式中的Clone方法可以利用某些框架中的序列化来实现深拷贝。(其他语言中需要利用框架)

6. 其他参考

C++设计模式------原型模式

相关推荐
宛 禾26 分钟前
Qt 控件入门:QLabel 从拖拽到对象树,一篇讲透
c++·qt·学习
hetao173383738 分钟前
联盟场-提高组-R7 & ZYZSC-S-Round 11
c++·算法
程序喵大人41 分钟前
【C++入门】编译链接模型 - 07 链接器怎样把符号对上号
开发语言·c++·编译器·编译链接·链接器
博风1 小时前
8、设计模式应用举例:适配器模式:Iterator接口与Enumeration接口
设计模式·适配器模式
局部有解1 小时前
Hot100 - 三数之和
数据结构·c++·算法
longlongzihan1 小时前
C++ 常用数据结构速查:vector、stack、queue、list、树、图、哈希表等声明与核心操作
数据结构·c++·list
别动我齐刘海2 小时前
实时控制学习2
linux·c++·人工智能·学习·算法
高晶2 小时前
ARM 嵌入式 Linux 系统 U-Boot 开发与移植实战M
设计模式·程序员
hetao17338373 小时前
校内场-提高组 ZYZSC-S-Round 2
c++·算法
hetao17338373 小时前
2026-10-14 hetao1733837 的刷题记录
c++·算法