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

设计模式 八:原型模式 (Prototype Pattern)

动机(Motivation)

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

解决方法:使用原型模式

原型模式是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而不是通过构造函数创建。 

基本概念

原型模式的核心思想是:

  • 创建一个原型接口,声明克隆方法

  • 具体类实现这个接口并提供克隆自身的能力

  • 客户端通过请求原型对象克隆自身来创建新对象

实现方式

1. 基本实现

#include <iostream>
#include <memory>// 原型基类
class Prototype {
public:virtual ~Prototype() = default;virtual std::unique_ptr<Prototype> clone() const = 0;virtual void print() const = 0;
};// 具体原型类
class ConcretePrototype : public Prototype {
public:ConcretePrototype(int value) : value_(value) {}// 复制构造函数实现克隆std::unique_ptr<Prototype> clone() const override {return std::make_unique<ConcretePrototype>(*this);}void print() const override {std::cout << "ConcretePrototype with value: " << value_ << std::endl;}void setValue(int value) {value_ = value;}private:int value_;
};int main() {// 创建原型对象auto prototype = std::make_unique<ConcretePrototype>(10);// 克隆对象auto clone1 = prototype->clone();auto clone2 = prototype->clone();// 修改克隆对象dynamic_cast<ConcretePrototype*>(clone1.get())->setValue(20);dynamic_cast<ConcretePrototype*>(clone2.get())->setValue(30);// 输出结果prototype->print();  // 输出: ConcretePrototype with value: 10clone1->print();     // 输出: ConcretePrototype with value: 20clone2->print();     // 输出: ConcretePrototype with value: 30return 0;
}

2. 使用原型管理器

#include <iostream>
#include <memory>
#include <unordered_map>class Prototype {
public:virtual ~Prototype() = default;virtual std::unique_ptr<Prototype> clone() const = 0;virtual void print() const = 0;
};class ConcretePrototypeA : public Prototype {
public:ConcretePrototypeA(int value) : value_(value) {}std::unique_ptr<Prototype> clone() const override {return std::make_unique<ConcretePrototypeA>(*this);}void print() const override {std::cout << "ConcretePrototypeA with value: " << value_ << std::endl;}private:int value_;
};class ConcretePrototypeB : public Prototype {
public:ConcretePrototypeB(std::string str) : str_(std::move(str)) {}std::unique_ptr<Prototype> clone() const override {return std::make_unique<ConcretePrototypeB>(*this);}void print() const override {std::cout << "ConcretePrototypeB with string: " << str_ << std::endl;}private:std::string str_;
};class PrototypeManager {
public:void registerPrototype(const std::string& key, std::unique_ptr<Prototype> prototype) {prototypes_[key] = std::move(prototype);}std::unique_ptr<Prototype> create(const std::string& key) {if (prototypes_.find(key) != prototypes_.end()) {return prototypes_[key]->clone();}return nullptr;}private:std::unordered_map<std::string, std::unique_ptr<Prototype>> prototypes_;
};int main() {PrototypeManager manager;// 注册原型manager.registerPrototype("A", std::make_unique<ConcretePrototypeA>(100));manager.registerPrototype("B", std::make_unique<ConcretePrototypeB>("Hello"));// 从原型创建对象auto obj1 = manager.create("A");auto obj2 = manager.create("B");auto obj3 = manager.create("A");if (obj1) obj1->print();  // 输出: ConcretePrototypeA with value: 100if (obj2) obj2->print();  // 输出: ConcretePrototypeB with string: Helloif (obj3) obj3->print();  // 输出: ConcretePrototypeA with value: 100return 0;
}

 UML结构

 

原型模式的优点

  1. 减少子类数量:不需要为每种对象创建专门的子类

  2. 动态配置应用:可以在运行时添加或删除原型

  3. 简化对象创建:特别是当对象初始化过程复杂时

  4. 性能优化:克隆通常比新建对象更高效

适用场景

  1. 当系统需要独立于其产品的创建、组合和表示时

  2. 当要实例化的类是在运行时指定时

  3. 当需要避免建立与产品类层次平行的工厂类层次时

  4. 当一个类的实例只能有几个不同状态组合中的一种时

注意事项

  1. 深拷贝与浅拷贝问题:确保克隆操作正确地复制了所有成员变量

  2. 对于包含循环引用的对象,需要特别处理克隆逻辑

  3. 原型模式可能隐藏了对象的创建细节,使代码更难理解

原型模式在C++中特别有用,因为它可以利用拷贝构造函数和赋值操作符来实现克隆操作,同时结合智能指针可以很好地管理内存。


文章转载自:
http://deputation .hfstrb.cn
http://microdontism .hfstrb.cn
http://urania .hfstrb.cn
http://hemolysin .hfstrb.cn
http://bulger .hfstrb.cn
http://landed .hfstrb.cn
http://civilize .hfstrb.cn
http://grisly .hfstrb.cn
http://dimidiate .hfstrb.cn
http://categorize .hfstrb.cn
http://benomyl .hfstrb.cn
http://talc .hfstrb.cn
http://either .hfstrb.cn
http://transplantation .hfstrb.cn
http://icebreaker .hfstrb.cn
http://rowdydow .hfstrb.cn
http://faddle .hfstrb.cn
http://ireful .hfstrb.cn
http://disassembly .hfstrb.cn
http://antimagnetic .hfstrb.cn
http://doctrinist .hfstrb.cn
http://abscondee .hfstrb.cn
http://yacket .hfstrb.cn
http://clinch .hfstrb.cn
http://amyloidosis .hfstrb.cn
http://fibrillose .hfstrb.cn
http://empennage .hfstrb.cn
http://squiffed .hfstrb.cn
http://crabstick .hfstrb.cn
http://xanthe .hfstrb.cn
http://www.dtcms.com/a/293940.html

相关文章:

  • Spring Boot全局异常处理:一网打尽Controller层异常,@RestControllerAdvice解析
  • 设计模式(单例)
  • 界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?
  • Linux下SVN常用指令
  • 设计模式代码总结
  • Android MediaCodec 的使用和源码实现分析
  • 路由器与交换机的区别
  • 从入门到精通:Windows右键菜单管理全解析
  • 为什么 Linux 启动后还能升级内核?
  • Jmeter的函数助手使用
  • 基于Dapr Sidecar的微服务通信框架设计与性能优化实践
  • 【软件系统架构】系列七:物联网云平台系统性能深入解析
  • HTTP性能优化终极指南:从协议原理到企业级实践
  • 视频、音频录制
  • 操作系统:系统调用的分类(Types of System Calls)
  • C++ 扫描局域网某个端口是否开放(如 5555 )(android adb) 线程并发加速
  • 3d移动translate3d
  • 秋招Day17 - Spring - Spring Boot
  • 【图像处理基石】如何实现一个车辆检测算法?
  • Nginx和Apache的区别
  • 多维任务筛选工具功能解析:如何通过智能筛选功能精准对接任务需求?
  • There are 2 missing blocks. The following files may be corrupted
  • 亚马逊AI新项目Starfish:重构电商Listing生态的机遇与挑战
  • 西班牙智能警示灯法案:引领欧洲智能交通新趋势
  • 0.0 深度学习资料网站
  • 工业控制系统的现状与发展趋
  • 分享一个tauri-plugin-http的工具类
  • python3写一个异步流式 http 接口服务调用大模型(async, stream, sanic)---6.2
  • 基于数据挖掘的短视频点赞影响因素分析【LightGBM、XGBoost、随机森林、smote】
  • 探索大语言模型(LLM):提升 RAG 性能的全方位优化策略