首页 > 其他分享 >设计模式之原型模式

设计模式之原型模式

时间:2024-06-02 13:59:51浏览次数:32  
标签:std 克隆 对象 创建 clone 模式 原型 设计模式

问题背景

在开发一个图形设计软件时,我们面临一个常见的需求:用户需要频繁地创建和编辑各种图形,如圆形、矩形和多边形。其中,许多图形元素在属性上非常相似,比如颜色、大小或样式可能只有细微的差别。用户希望能够快速复制一个已有图形,然后对其进行小的修改,而不是每次都从零开始创建。这不仅能节省时间,还可以提高整体的工作效率。

问题分析

原型模式通过允许对象复制自身来支持这种需求,这是一种创建型设计模式,特别适合于创建成本较高的情况。在图形设计软件中,使用原型模式可以让用户快速复制和自定义复杂的图形元素,而无需知道对象的具体类。这种方式可以极大地简化创建过程,特别是在涉及复杂对象(需要复杂的初始化参数)的场景中。

代码部分

定义抽象原型和具体原型

#include <iostream>
#include <unordered_map>
#include <memory>
#include <string>

// 抽象原型类 - Shape
class Shape {
public:
    // 克隆函数,用于复制对象
    virtual std::shared_ptr<Shape> clone() const = 0;
    // 绘制函数,纯虚函数需要在子类中实现
    virtual void draw() const = 0;
    // 虚析构函数,确保在销毁对象时调用派生类的析构函数
    virtual ~Shape() {}
};

// 具体原型类 - Circle
class Circle : public Shape {
private:
    std::string color; // 圆的颜色
    int radius; // 圆的半径

public:
    // 构造函数,初始化圆的颜色和半径
    Circle(const std::string& color, int radius) : color(color), radius(radius) {}
    
    // 克隆函数,返回一个当前对象的副本
    std::shared_ptr<Shape> clone() const override {
        return std::make_shared<Circle>(*this); // 使用当前对象的拷贝构造函数创建副本
    }
    
    // 绘制函数,输出绘制圆的信息
    void draw() const override {
        std::cout << "Drawing a " << color << " circle with radius " << radius << std::endl;
    }
};
// 具体原型类 - Rectangle
class Rectangle : public Shape {
private:
    std::string color; // 矩形的颜色
    int width; // 矩形的宽度
    int height; // 矩形的高度

public:
    // 构造函数,初始化矩形的颜色、宽度和高度
    Rectangle(const std::string& color, int width, int height) : color(color), width(width), height(height) {}
    
    // 克隆函数,返回一个当前对象的副本
    std::shared_ptr<Shape> clone() const override {
        return std::make_shared<Rectangle>(*this); // 使用当前对象的拷贝构造函数创建副本
    }
    
    // 绘制函数,输出绘制矩形的信息
    void draw() const override {
        std::cout << "Drawing a " << color << " rectangle with width " << width << " and height " << height << std::endl;
    }
};

实现原型管理器

#include <unordered_map>
#include <memory>
#include <string>

// 原型管理器类
class PrototypeManager {
private:
    std::unordered_map<std::string, std::shared_ptr<Shape>> prototypes; // 存储原型对象的哈希表

public:
    // 注册原型对象
    void registerPrototype(const std::string& key, std::shared_ptr<Shape> prototype) {
        prototypes[key] = prototype; // 将原型对象存储到哈希表中
    }

    // 获取原型对象
    std::shared_ptr<Shape> getPrototype(const std::string& key) {
        // 通过键值查找原型对象,并调用其克隆函数返回一个副本
        return prototypes[key]->clone();
    }
};

使用原型模式在客户端代码中创建和修改图形对象

int main() {
    // 创建原型管理器对象
    PrototypeManager manager;
    
    // 注册原型对象:大红色圆形和小蓝色矩形
    manager.registerPrototype("large red circle", std::make_shared<Circle>("red", 10));
    manager.registerPrototype("small blue rectangle", std::make_shared<Rectangle>("blue", 5, 3));

    // 获取原型对象的副本
    auto circle = manager.getPrototype("large red circle"); // 获取大红色圆形的副本
    auto rectangle = manager.getPrototype("small blue rectangle"); // 获取小蓝色矩形的副本

    // 绘制图形
    circle->draw(); // 绘制大红色圆形
    rectangle->draw(); // 绘制小蓝色矩形

    return 0;
}

代码分析

抽象原型类(Shape)

  • Shape类 定义了一个接口,包括clone()draw()两个方法。这是原型模式的核心,因为clone()方法提供了一种方式来创建对象的副本。
  • clone()是纯虚函数,强制要求派生类实现具体的克隆逻辑。
  • draw()也是一个虚函数,用于在屏幕上绘制形状。
  • 析构函数是虚的,保证派生类的正确析构。

具体原型类(Circle和Rectangle)

  • Circle类和Rectangle类Shape类的具体实现。它们实现了clone()方法,通过拷贝构造函数来克隆自身,返回一个新的共享指针指向克隆对象。
  • 这些类也实现了draw()方法,具体化了如何绘制自己。
  • Circle类包含颜色和半径属性;Rectangle类包含颜色、宽和高属性。这些属性在构造函数中被初始化。

原型管理器(PrototypeManager)

  • PrototypeManager类 管理一组原型对象,允许客户端注册新的原型或通过名字获取原型的克隆。
  • 使用std::unordered_map来存储字符串键和形状原型的映射。
  • registerPrototype()方法将原型与键绑定存储在映射中。
  • getPrototype()方法通过键来查找并克隆存储的原型。

客户端使用

  • main()函数中,首先创建一个PrototypeManager实例。
  • 注册了两个原型:“large red circle”和“small blue rectangle”。
  • 通过原型名称获取原型的克隆,并调用它们的draw()方法来绘制。
  • 这样客户端可以使用原型模式来避免直接构造具体类的实例,而是通过复制现有实例来创建新实例。

原型模式的编程要点可以总结为以下几个关键方面:

  1. 定义抽象原型类(Prototype):这个类声明了一个克隆自身的接口,通常是一个clone方法,用于生成对象自身的一个完整拷贝。在示例中,Shape是一个抽象原型类,定义了clone()方法作为克隆接口。

  2. 实现具体原型类(Concrete Prototype):具体原型类实现抽象原型的clone方法,在此方法中返回其对象的一个完整拷贝。例如,CircleRectangle类分别重写了clone方法,用来复制自身的实例。

  3. 使用深拷贝:通常在实现clone方法时,需要确保进行深拷贝以避免副本与原始对象之间的依赖。这意味着复制的对象应包括其所有的成员变量的新实例,确保原型的完整和独立。

  4. 原型管理器(Prototype Manager):管理器类用于存储一个原型注册表,其中包含了系统中所有可用的原型对象。管理器提供注册和查找原型的功能。在代码示例中,PrototypeManager类使用一个哈希表存储注册的原型,并通过键值对进行访问和克隆。

  5. 克隆操作的隐含意义:原型模式不仅仅是复制一个对象,更是一种避免复杂对象创建开销的策略,特别是当对象的创建过程复杂或资源消耗较大时。

  6. 客户端的简化操作:客户端可以通过管理器获取已注册的原型的副本,然后根据需要修改这些副本,而无需了解对象的具体类别。这降低了系统的复杂性,并提高了代码的复用性。

优点

  • 降低复杂性:客户端无需知道具体的类,只需要知道如何操作接口。
  • 动态管理:可以在运行时动态地添加或删除原型。
  • 优化性能:通过复制已有对象来避免重新初始化对象,尤其在创建复杂对象时。

潜在的改进点

  • getPrototype()方法中,可能需要增加对键不存在的异常处理。如果键不在映射中,应该返回null或抛出异常。
  • 可以考虑增加一些功能,例如删除注册的原型,或者列出所有注册的原型。

通过实现原型模式,我们可以看到如何有效地复制和管理图形对象。该模式不仅减少了创建复杂对象的复杂性,还提高了系统的灵活性和扩展性。用户可以通过简单地复制和调整现有的图形对象来创建新的对象,这对于图形设计软件是一个巨大的优势。

结语

通过本文的探讨和示例实现,我们详细了解了原型模式在C++中的应用,尤其是在图形编辑软件的开发场景中。原型模式通过允许对象复制自身,为处理如图形对象这样的复杂对象提供了一个高效和灵活的创建策略。

原型模式的核心优势包括:

  • 减少创建操作的复杂性:原型模式使得复制一个复杂对象变得简单,避免了新对象创建过程中需要的重复步骤。
  • 增加程序的动态性:可以在运行时通过注册和删除原型来动态地增加或减少产品的数量。
  • 优化性能和资源利用:通过复制已有对象来避免重复的初始化操作,从而节省了资源和提高了性能,尤其是当对象的创建成本较高时。

在图形编辑器示例中,我们展示了如何利用原型模式来管理和复制图形对象。通过注册不同的图形原型到原型管理器,我们能够在运行时根据需求轻松地复制任何已注册的图形对象。这种方法不仅简化了代码,还增强了系统的可维护性和扩展性。

标签:std,克隆,对象,创建,clone,模式,原型,设计模式
From: https://blog.csdn.net/karl2000/article/details/138495971

相关文章

  • 【Vue】深入理解MVVM模式的魔力
    目录前言一、MVVM模式是什么?二、具体示例总结前言    Vue.js是一种基于JavaScript的前端框架,它采用了MVVM(Model-View-ViewModel)模式来实现数据的双向绑定。在本篇博客中,我将介绍MVVM模式的基本概念,并演示如何使用Vue.js来实现这种模式。一、MVVM模式是什么? ......
  • 抽象工厂模式
    抽象工厂模式解决的是一系列相互依赖的对象的创建。classMyConnect{};classMyDatabse{};classMyCommand{};//sqlServer的连接classSqlServerConnect:publicMyConnect{};classSqlServerDatabse:publicMyDatabse{};classSqlServerCommand:publicMyComm......
  • 单例模式线程安全reorder问题
    单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。下面是一个使用C++实现的线程安全的单例模式的例子:classSingleton{private:staticstd::atomic<Singleton*>instance;//静态私有实例指针使用原子操作类atomic线程安全sta......
  • 观察者设计模式
    实现C++中的观察者设计模式通常包括以下几个关键组件: 1.**Subject(主题)**:这是被观察的对象,它维护一个观察者列表,并提供注册、注销观察者的方法以及通知所有观察者的方法。 2.**Observer(观察者)**:这是一个抽象接口或基类,定义了观察者需要实现的更新接口(如`update()`方法),以......
  • 反海淘商业模式案例分析 :Pandabuy淘宝代购集运系统解析丨1688代采集运系统
    反海淘商业模式是指通过代购、代采集运等方式,帮助海外消费者购买并运输国内商品的一种商业模式。这种模式可以帮助海外消费者解决购买国内商品的困难,同时也为国内商家提供了一个新的销售渠道。下面以Pandabuy淘宝代购集运系统和1688代采集运系统为例进行解析。Pandabuy淘宝代......
  • (JAVA)设计模式-适配器模式
    模式的定义和特点:适配器模式(Adapter)是一种将一个类的接口转换成客户希望的另外一个接口的设计模式,可以提高代码的复用性和灵活性。结构与实现:定义一个适配器类来实现业务接口,再继承现有组件库中已经存在的组件。示例:创建业务接口类:点击查看代码publicinte......
  • 共享门店:革新商业模式,实现资源最大利用
    共享门店+股东分红模式一、模式概述共享门店+股东分红模式是一种结合了共享经济和传统实体门店的新型商业模式。在这种模式下,多个品牌或商家共同使用同一门店空间,通过共享资源、资金和客户资源,降低经营成本,提高资源利用效率,扩大市场渠道,同时,股东们可以根据其持股比例享受门店......
  • 什么是共享门店模式?
    共享门店+股东分红模式一、模式概述共享门店+股东分红模式是一种结合了共享经济和传统实体门店的新型商业模式。在这种模式下,多个品牌或商家共同使用同一门店空间,通过共享资源、资金和客户资源,降低经营成本,提高资源利用效率,扩大市场渠道,同时,股东们可以根据其持股比例享受门店......
  • UMLChina为什么叒要翻译《分析模式》?
    UMLChina受机械工业出版社委托,重新翻译《分析模式》。MartinFowler的“AnalysisPatterns,ReusableObjectModels”,原书出版于1997年,至今为止未出第2版。2004年,机械工业出版社出版该书中译本《分析模式》。2020年,人民邮电出版社重新翻译,出版新的中译本《分析模式》。这一......
  • [缝合故事]1999-幻影战斗机《分析模式》和分析模式(1)
    DDD领域驱动设计批评文集做强化自测题获得“软件方法建模师”称号《软件方法》各章合集题目没错吧?是不是手抖,多粘贴了一个“分析模式”?分析模式≠《分析模式》,这个区别后面再说。一、UMLChina和《分析模式》的故事2001年5月,UMLChina发布了电子杂志《非程序员》第1期,上面......