专业编程基础技术教程

网站首页 > 基础教程 正文

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

ccvgpt 2024-10-12 13:51:49 基础教程 7 ℃

原型模式概述

原型模式(Prototype)定义:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

原型模式(Prototype)正是提供了自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。在C++中,拷贝构造函数(Copy Constructor)分成浅层拷贝和深层拷贝,是系统崩溃的根源之一。

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

原型模式的工作原理是将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程。从工厂方法角度而言,创建新对象的工厂就是原型类自己。软件系统中有些对象的创建过程比较复杂,且有时需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在。

原型模式结构

原型模式的结构包含以下几个角色:

  • 抽象原型类(AbstractPrototype):声明克隆clone自身的接口。
  • 具体原型类(ConcretePrototype):实现clone接口。
  • 客户端(Client):客户端中声明一个抽象原型类,根据客户需求clone具体原型类对象实例。

原型模式UML类图如下:

克隆的方法

(1) 浅拷贝

在浅拷贝中,如果原型对象的成员变量是值类型(如int、 double、 char等基本数据类型),将复制一份给拷贝对象;如果原型对象的成员变量是引用/指针,则将引用/指针指向的地址拷贝一份给拷贝对象,即原型对象和拷贝对象中的成员变量指向同一个地址。

(2) 深拷贝

在深拷贝中,无论原型对象中的成员变量是值类型还是指针/引用类型,都将复制一份给拷贝对象。浅拷贝和深拷贝的区别,如图所示:

代码:

// 原型模式.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
using namespace std;
class AbstractPrototype
{
public:
  AbstractPrototype() { strName = ""; }
  AbstractPrototype(string name) { strName = name; }
  virtual ~AbstractPrototype() {}
  virtual AbstractPrototype* clone() = 0;
  virtual void ReviseName(string name) { strName = name; }
  virtual void GetNameInfo() { cout << strName << endl; }
protected:
  string strName;
};
class ConcretePrototypeA : public AbstractPrototype
{
public:
  ConcretePrototypeA() {}
  ConcretePrototypeA(string name) : AbstractPrototype(name) {}
  ~ConcretePrototypeA() {}
  AbstractPrototype* clone()
  {
    ConcretePrototypeA* pType = new ConcretePrototypeA();
    pType->strName = this->strName;
    return pType;
  }
};
class ConcretePrototypeB : public AbstractPrototype
{
public:
  ConcretePrototypeB() {}
  ConcretePrototypeB(string name) : AbstractPrototype(name) {}
  ~ConcretePrototypeB() {}
  AbstractPrototype* clone()
  {
    ConcretePrototypeB* pType = new ConcretePrototypeB();
    pType->strName = this->strName;
    return pType;
  }
};
int main()
{
  //具体A克隆出B
  ConcretePrototypeA* pTypeA = new ConcretePrototypeA("ConcretePrototypeA");
  ConcretePrototypeB* pTypeB = reinterpret_cast<ConcretePrototypeB*>(pTypeA->clone());
  pTypeA->GetNameInfo();
  pTypeB->GetNameInfo();
  //具体B克隆出A
  pTypeB->ReviseName("ConcretePrototypeB");
  pTypeA = reinterpret_cast<ConcretePrototypeA*>(pTypeB->clone());
  pTypeA->GetNameInfo();
  pTypeB->GetNameInfo();
  return 0;
}

最近发表
标签列表