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

下面我将详细讲解 C++ 设计模式之原型模式的完整攻略。

什么是原型模式?

原型模式是一种创建者模式,它通过复制现有对象来创建新对象,而不是直接实例化新对象。它通过在运行时动态生成对象副本的方式来创建新对象,避免了创建新对象的成本,并提高了性能。

原型模式的优缺点

优点:

  • 在运行时生成新对象,避免了创建新对象的成本。
  • 代码复杂度低,易于实现。
  • 可以实现对象动态配置。

缺点:

  • 所有的克隆方法都必须在导出类中实现。
  • 克隆方法是递归的,需要额外的递归调用开销。
  • 深克隆可能需要额外的编写代码和测试。

原型模式的实现方式

原型模式的实现方式可以采用两种方式来实现:浅拷贝和深拷贝。

浅拷贝:将一个对象复制到另一个对象中,新对象中的基本元素是源对象中相应元素的副本。这种方法比较简单,但如果源对象包含指向其他对象的指针,新对象中的指针将指向源对象中的相应指针所指向的地址,这种方法可能会引起问题。

深拷贝:将源对象的所有元素递归地复制到新对象中,使二者完全独立。这种方式比较安全,但开销比较大。

原型模式的实现步骤

  1. 定义一个抽象类或接口。
class ICloneable {
public:
    virtual ICloneable* Clone() = 0;
};
  1. 定义一个需要被克隆的对象。
class Person : public ICloneable {
public:
    string name;
    int age;
    Date birthday;
    vector<Address*> addresses;

    virtual ICloneable* Clone() {
        // 深拷贝实现
        Person* p = new Person(*this);
        // 指针地址修改为新对象的地址
        for (size_t i = 0; i < p->addresses.size(); i++) {
            Address* a = p->addresses[i];
            a = new Address(*a);
            p->addresses[i] = a;
        }
        return p;
    }
};
  1. 在需要克隆对象的位置进行调用,调用 Clone() 方法生成新对象。
int main() {
    Person* p1 = new Person();
    p1->name = "Tom";
    p1->age = 25;
    p1->birthday.year = 1996;
    p1->birthday.month = 7;
    p1->birthday.day = 5;
    p1->addresses.push_back(new Address("China", "Beijing"));
    p1->addresses.push_back(new Address("USA", "New York"));

    Person* p2 = (Person*)p1->Clone();
    // 修改新对象的值
    p2->name = "Jerry";
    p2->age = 30;
    p2->birthday.year = 1991;
    p2->birthday.month = 1;
    p2->birthday.day = 1;
    p2->addresses[0]->city = "Shanghai";
    p2->addresses[1]->city = "Los Angeles";

    return 0;
}

这样,在 main() 函数中,我们通过将原始对象 p1 传递到 Clone() 方法中生成新的对象 p2,并修改新对象的值。如果进行的是浅拷贝的实现方式,新对象 p2 将会和原始对象 p1 共享同一个地址空间,修改 p2 的值将会对 p1 也造成影响。而深拷贝由于同字符串常量池的使用后续会大批量申请内存非常占用,而weak_ptr又不稳定,为了解决深拷贝的问题,可以使用单例模式或者原型模式,进行共享部分的复用。

示例说明

下面给出两个典型的原型模式的示例,分别为“周报”和“简历”。

示例 1:周报

解释:每周要填写周报,内容格式固定。周报分为几个部分,例如工作内容、进度、问题、计划等,这些部分可能需要不断重复使用和填写。如果每次都需要手动填写,那么效率就会比较低。因此,这个时候,我们可以通过原型模式来解决这个问题。

首先,我们定义一个周报类,包含如下内容:

class WeeklyReport {
public:
    string name;
    string date;
    vector<string> workContent;
    vector<string> progress;
    vector<string> problems;
    vector<string> plan;

    ICloneable* Clone() {
        WeeklyReport* report = new WeeklyReport(*this);
        return report;
    }
};

同时,定义一个周报管理类,负责管理周报模板和实例:

class WeeklyReportManager {
public:
    unordered_map<string, WeeklyReport*> templates;

    // 注册模板
    void RegisterTemplate(string name, WeeklyReport* report) {
        templates[name] = report;
    }

    // 获取模板副本
    WeeklyReport* GetTemplate(string name) {
        return (WeeklyReport*)templates[name]->Clone();
    }
};

在运行时,我们只需加载多个周报模板,并且把需要的模板复制后修改,就可以快速地完成周报的填写。

示例 2:简历

解释:每次求职时,都需要撰写一份新的简历。如果每次都需要从头开始撰写,那么很难避免繁琐的重复劳动。同时,简历中的很多内容可能是可以公用的,例如教育经历、工作经历、项目经历等。这个时候,我们可以通过原型模式来实现简历的快速生成。

首先,我们定义一个简历类,包含如下内容:

class Resume {
public:
    string name;
    string email;
    vector<Education*> educations;
    vector<Work*> works;
    vector<Project*> projects;

    ICloneable* Clone() {
        Resume* resume = new Resume(*this);
        return resume;
    }
};

同时,定义一个简历模板管理类,负责管理简历模板和实例:

class ResumeTemplateManager {
public:
    unordered_map<string, Resume*> templates;

    // 注册模板
    void RegisterTemplate(string name, Resume* resume) {
        templates[name] = resume;
    }

    // 获取模板副本
    Resume* GetTemplate(string name) {
        return (Resume*)templates[name]->Clone();
    }
};

在运行时,我们只需加载多个简历模板,并且把需要的模板复制后修改,就可以快速地完成简历的撰写。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++设计模式之原型模式 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C/C++中CJSON的使用(创建与解析JSON数据)

    下面我就为你详细讲解C/C++中CJSON的使用,包括创建和解析JSON数据的完整攻略,并且会提供两条代码示例来帮助你更好地理解。 什么是CJSON? CJSON是一个小型的C库,用于解析和生成JSON数据。它允许你在C程序中轻松地解析JSON,创建JSON数据和与JSON数据进行交互。CJSON库只包含了一个头文件,非常适合嵌入式设备和其它需要小型JSON…

    C 2023年5月22日
    00
  • VCPKG安装和使用教程(经验总结)

    VCPKG安装和使用教程(经验总结) VCPKG是一个跨平台的C++库管理器,它可以简化C++库的安装和使用流程。本教程将详细讲解如何安装和使用VCPKG。 安装VCPKG 下载VCPKG 可以从VCPKG的GitHub仓库中下载最新版本的VCPKG:https://github.com/microsoft/vcpkg/releases 安装VCPKG 解压…

    C 2023年5月23日
    00
  • C语言流程控制之switch语句详解

    C语言流程控制之switch语句详解是本网站总结的一篇C语言教程文章,主要介绍了switch语句的用法和注意事项。本文将通过以下几个方面详细讲解: 1. switch语句的基本格式 switch语句由一个表达式和多个case组成,如下所示: switch(expression){ case constant-expression1: statement1; …

    C 2023年5月23日
    00
  • Visual Studio 2022 的安装和创建C++项目(图文教程)

    下面是详细讲解 Visual Studio 2022 的安装和创建 C++ 项目的攻略: 1.下载和安装 Visual Studio 2022 首先,我们需要下载并安装 Visual Studio 2022。可以在微软官网上下载安装包,具体流程如下: 1.1 访问 Visual Studio 官网 首先,在浏览器中访问 Visual Studio 官网。 1…

    C 2023年5月30日
    00
  • C++ class和struct到底有什么区别详解

    C++中的class和struct定义方式非常相似,都可以包含成员变量和成员函数,甚至可以互相继承。但实际上,class和struct还是存在一些差别的。下面从以下三个方面对它们进行详细的比较: 定义语法 在定义上,class和struct的语法非常相似,但是有一个小差别: // 定义class class MyClass { public: int a; …

    C 2023年5月23日
    00
  • C语言实现实验设备管理系统

    C语言实现实验设备管理系统 简介 C语言是一种面向过程的编程语言,广泛应用于系统软件、存储管理、操作系统、网络协议等领域。实验设备管理系统是一种重要的实验室管理工具,在实验室管理中得到广泛应用。本文将详细讲解如何使用C语言实现实验设备管理系统。 环境配置 在开始编写代码之前,需要先配置好C语言的开发环境。以下是环境配置的基本步骤: 安装C语言编译器,建议选择…

    C 2023年5月23日
    00
  • C语言实现学生成绩等级划分的方法实例

    C语言实现学生成绩等级划分的方法实例 概述 本文将介绍如何使用C语言实现学生成绩等级划分的方法,并提供两个示例说明。 学生成绩等级划分是一个常见的应用场景,可以帮助老师和学生更加清楚地了解学生成绩的情况,方便对学生进行教学和管理。 在本文中,我们将介绍如何使用C语言实现一个学生成绩等级划分程序,以及如何进行测试。 步骤 1.明确需求 我们需要设计一个C语言程…

    C 2023年5月23日
    00
  • C语言和go语言之间的交互操作方法

    C语言和Go语言是两种不同的编程语言,它们在程序的实现上也存在一些差异。但是,由于它们在不同的应用场景下产生了巨大的价值,所以在很多时候是需要将这两种语言进行交互的。那么,如何实现C语言和Go语言的交互呢?下面是一个完整的攻略。 一、Go与C交互的基本方法 Go和C使用的是不同的编译器和标准库,因此它们之间的交互需要一些特殊的技巧。 首先,我们需要了解在Go…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部