当前位置: 首页 > news >正文

05创建型设计模式——原型模式

一、原型模式简介

        原型模式(Prototype Pattern)模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的数据。

1)由原型对象自身创建目标对象。换句话说,对象创建这一动作发自原型对象本身。

2)目标对象是原型对象的一个克隆(clone)。也就是说,通过原型模式创建的对象,不仅与原型对象具有相同的结构,还与原型对象具有相同的值。

原型模式具有浅克隆和深克隆之分。***深浅克隆的原型模式各有各的优势。

  • 浅克隆:复制对象的所有属性,但对于引用类型属性,仅复制引用。这会使得新对象与原始对象共享引用类型的内存空间。
  • 深克隆:复制对象的所有属性,即使是引用类型,也会创建新的实体,并复制指向这些实体的引用。这样新对象就与原始对象完全独立了。
原型模式的结构图

二、原型模式的用处

原型模式适用于需要多个一模一样的复杂对象,让其具有自我复制功能,统一一套接口。

 原型模式说白了它允许对象复制现有的对象,而不是每次都通过外部new关键字来创建新的对象。这种模式有助于减少对象的创建时间,特别是当对象初始化的成本较高时。原型模式的关键在于它使用一个原型对象来创建新的实例,而不是通过直接生成它们。

原型模式优点:

  1. 对象初始化成本较高,可以避免通过复制现有对象来减少创建时间。
  2. 避免编写复杂的工厂方法来生成各种对象。
  3. 当你想支持对象的深克隆或浅克隆时。

原型模式注意点:

  • 当原型及其后代需要支持克隆行为时,这种方法非常有效。
  • 如果没有对象的克隆能力,或者你的领域不支持“克隆”,原型模式可能不合适。
  • 使用原型模式时要确保能够处理循环引用的情况。

三、原型模式的设计方法

浅克隆的原型模式

        背景:假设我们有一个电子邮件系统,其中每封邮件都包含一个附件。当我们想要复制一封邮件时,我们可能不需要复制附件的实际内容,而只需要复制邮件的其他信息和对附件的引用。这种情况下,浅克隆是非常合适的选择。

shallow_Prototype.cpp
#include <iostream>
#include <cstring>//附件
class Attachment {
private:std::string fileName;public:Attachment(const std::string& name) : fileName(name) {}std::string getFileName() const {return fileName;}// 返回 fileName 的地址const std::string* getFileNameAddress() const {return &fileName;}Attachment* clone() const {return new Attachment(*this);}
};//邮件
class Email {
public:Email(const std::string& sender, const std::string& recipient, const std::string& body, Attachment* attachment): sender(sender), recipient(recipient), body(body), attachment(attachment) {}Email(const Email& other): sender(other.sender), recipient(other.recipient), body(other.body), attachment(other.attachment) {}~Email() {// 注意:这里没有删除附件,因为我们假设多个邮件共享同一个附件// 如果实现深拷贝,需要在此处删除附件}Email* clone() const {return new Email(*this);}void print() const {std::cout << "Sender: " << sender << std::endl;std::cout << "Recipient: " << recipient << std::endl;std::cout << "Body: " << body << std::endl;std::cout << "Attachment: " << (attachment ? attachment->getFileName() : "None") << std::endl;}Attachment* getAttachment() const {return attachment;
}private:std::string sender;std::string recipient;std::string body;Attachment* attachment;
};//模拟接口
void doWorking() {// 创建附件对象Attachment* attachment = new Attachment("document.pdf");// 创建邮件对象Email originalEmail("alice@example.com", "bob@example.com", "Hi Baby!", attachment);// 克隆邮件对象Email* clonedEmail = originalEmail.clone();// 打印原始邮件和克隆邮件的信息std::cout << "Original Email:" << std::endl;originalEmail.print();std::cout << std::endl << "Cloned Email:" << std::endl;clonedEmail->print();// 检查附件对象是否被共享(共享说明是浅克隆)std::cout << std::endl << "原始附件: " << originalEmail.getAttachment()->getFileName() << " 原始附件地址: " << originalEmail.getAttachment()->getFileNameAddress() << std::endl;std::cout << "深克隆附件: " << clonedEmail->getAttachment()->getFileName() << " 深克隆附件地址: " << clonedEmail->getAttachment()->getFileNameAddress() << std::endl;// 清理资源delete clonedEmail;return ;
}int main() {//调用doWorking();return 0;
}

运行效果 

深克隆的原型模式
deep_Prototype.cpp
#include <iostream>
#include <cstring>//附件
class Attachment {
private:std::string fileName;public:Attachment(const std::string& name) : fileName(name) {}std::string getFileName() const {return fileName;}// 返回 fileName 的地址const std::string* getFileNameAddress() const {return &fileName;}Attachment* clone() const {return new Attachment(*this);}
};//邮件
class Email {
public:Email(const std::string& sender, const std::string& recipient, const std::string& body, Attachment* attachment): sender(sender), recipient(recipient), body(body), attachment(attachment ? attachment->clone():nullptr) {}Email(const Email& other): sender(other.sender), recipient(other.recipient), body(other.body), attachment(other.attachment ? other.attachment->clone():nullptr) {}~Email() {delete attachment;// 删除附件,避免内存泄漏}Email* clone() const {return new Email(*this);}void print() const {std::cout << "Sender: " << sender << std::endl;std::cout << "Recipient: " << recipient << std::endl;std::cout << "Body: " << body << std::endl;std::cout << "Attachment: " << (attachment ? attachment->getFileName() : "None") << std::endl;}Attachment* getAttachment() const {return attachment;
}private:std::string sender;std::string recipient;std::string body;Attachment* attachment;
};//模拟接口
void doWorking() {// 创建附件对象Attachment* attachment = new Attachment("document.pdf");// 创建邮件对象Email originalEmail("alice@example.com", "bob@example.com", "Hi Baby!", attachment);// 克隆邮件对象Email* clonedEmail = originalEmail.clone();// 打印原始邮件和克隆邮件的信息std::cout << "Original Email:" << std::endl;originalEmail.print();std::cout << std::endl << "Cloned Email:" << std::endl;clonedEmail->print();std::cout << std::endl << "原始附件: " << originalEmail.getAttachment()->getFileName() << " 原始附件地址: " << originalEmail.getAttachment()->getFileNameAddress() << std::endl;std::cout << "深克隆附件: " << clonedEmail->getAttachment()->getFileName() << " 深克隆附件地址: " << clonedEmail->getAttachment()->getFileNameAddress() << std::endl;// 清理资源delete clonedEmail;delete attachment;return ;
}int main() {//调用doWorking();return 0;
}

运行效果

四、总结

原型模式的深拷贝和浅拷贝技术其实就是利用了指针的特性,指针本身具有指向的作用,当指针指向了堆区没有任何方法去拷贝或析构该堆区的数据,就造成了多个指针指向同一个堆区空间或多次析构的问题。


http://www.mrgr.cn/news/4107.html

相关文章:

  • 汇凯贵金属:金子在家怎么清洗才干净
  • 非常nice! IDEA远程Debug调试程序
  • epoll机制中最核⼼的数据结构是什么?
  • 并查集在哪些具体应用中最常用
  • 计算机相关法律法规及违规案例
  • 机器学习在旅游业的革新之旅
  • ubuntu18.04更改系统语言及换源的方法步骤
  • 深入解析css-学习小结
  • C语言 | Leetcode C语言题解之第342题4的幂
  • PostgreSQL的pg_dump中 --inserts参数测试
  • CMOS 逆变器的功耗
  • WPS Office两个严重漏洞曝光,已被武器化且在野利用
  • MCU数据采集模块:核心功能与工作机制深度解析
  • Verilog刷题笔记55
  • Ubuntu清除缓存的方法--防止系统崩溃
  • 麻将手游开发的未来之路:技术与创新并行
  • TOMCAT入门到精通
  • Simple RPC - 04 从零开始设计一个客户端(上)
  • 多重示例详细说明Eureka原理实践
  • mockjs的使用