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

2023-10-23 18:01

本文主要是介绍C++设计模式_10_ Prototype 原型模式(小模式,不太常用),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

文章目录

  • 1. 动机 (Motivation)
  • 2. 代码演示Prototype 原型模式
    • 2.1 Prototype.cpp
    • 2.2 ConcretePrototype.cpp
    • 2.3 Client
  • 3. 模式定义
  • 4. 结构
  • 5. 要点总结
  • 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个类合并起来。

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

变为以下形式:

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

并修改类的名字得到:

Prototype.cpp

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

2.2 ConcretePrototype.cpp

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

ConcretePrototype.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则变为:

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++设计模式——原型模式

这篇关于C++设计模式_10_ Prototype 原型模式(小模式,不太常用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/269534

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

Python打包成exe常用的四种方法小结

《Python打包成exe常用的四种方法小结》本文主要介绍了Python打包成exe常用的四种方法,包括PyInstaller、cx_Freeze、Py2exe、Nuitka,文中通过示例代码介绍的非... 目录一.PyInstaller11.安装:2. PyInstaller常用参数下面是pyinstal

Python 常用数据类型详解之字符串、列表、字典操作方法

《Python常用数据类型详解之字符串、列表、字典操作方法》在Python中,字符串、列表和字典是最常用的数据类型,它们在数据处理、程序设计和算法实现中扮演着重要角色,接下来通过本文给大家介绍这三种... 目录一、字符串(String)(一)创建字符串(二)字符串操作1. 字符串连接2. 字符串重复3. 字

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

python语言中的常用容器(集合)示例详解

《python语言中的常用容器(集合)示例详解》Python集合是一种无序且不重复的数据容器,它可以存储任意类型的对象,包括数字、字符串、元组等,下面:本文主要介绍python语言中常用容器(集合... 目录1.核心内置容器1. 列表2. 元组3. 集合4. 冻结集合5. 字典2.collections模块

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法