前言

尊重原创,本系列文本解析部分主要基于Candidate for Master’s Degree School of Computer Wuhan University的K_Eckel([email protected])《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》。为了避免重造轮子,本系列博文对源码在ubuntu16.04下做了验证并上传到了gitee,再次感谢。

如有问题,可邮件联系我([email protected])并共同探讨解决方案。

目录

创建型模式(Creating Pattern)

Factory 模式 | AbstactFactory 模式 | Singleton 模式 | Builder 模式 | Prototype 模式

结构型模式(Structrual Pattern)

Bridge 模式 | Adapter 模式 | Decorator 模式 | Composite 模式 | Flyweight 模式 | Facade 模式 | Proxy 模式

行为型模式(Behavioral Pattern)

Template 模式 | Strategy 模式 | State 模式 | Observer 模式 | Memento 模式 | Mediator 模式 | Command 模式 | Visitor 模式 | Iterator 模式 | Interpreter 模式 | Chain of Responsibility 模式

Prototype 模式简介

原型(Prototype)模式是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

**思想:**克 隆一个已有的类的实例(大家相比都用过甚至写过类的Clone实现,应该很容易理解了)。

**场景:**应 用Clone的场景应该说非常多,理想情况下我当然希望任何类都能Clone, 需要的时候就能Clone一份一模一样的出来。

**实现:**这 里将的实现主要之实现的表现形式,而不是如何用具体的语言来实现。因此,只要为需要Clone能力 的类定义一个Clone方法就行。当然,一般,主流的程序语言框架都已经定义了通用的Clone接 口(当然也可以自己定义),继承并实现该接口和方法就好。

**实例:**Prototype模式提供了一个通过已存在对象进行新对象创建的接口(Clone), Clone()实现和具体的语言相关,在C++中通过拷贝构造函数实现。

问题

关于这个模式,突然想到了小时候看的《西游记》,齐天大圣孙悟空再发飙的时候可以通过自己头上的 3 根毛立马复制出来成千上万的孙悟空,对付小妖怪很管用(数量最重要)。Prototype 模式也正是提供了自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。在 C++中拷贝构造函数(Copy Constructor)曾经是很对程序员的噩梦,浅层拷贝和深层拷贝的魔魇也是很多程序员在面试时候的快餐和系统崩溃时候的根源之一。

模式选择

Prototype 模式典型的结构图为:

图 1:Prototype Pattern 结构图

Prototype 模式提供了一个通过已存在对象进行新对象创建的接口Clone,Clone()实现和具体的实现语言相关,在 C++中我们将通过拷贝构造函数实现之。

实现

完整代码示例(code)

Prototype 模式的实现比较简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用 C++实现,并在 Visual Studio Code,Version: 1.36.1 下测试运行)。

源码gitee地址:点击这里

代码目录结构:

patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Prototype/src$ tree ../
../
├── include
│   └── Prototype.h
└── src
    ├── main.cpp
    └── Prototype.cpp

2 directories, 3 files

Prototype.h:

// Prototype.h

#ifndef _PROTOTYPE_H_
#define _PROTOTYPE_H_

class Prototype {
 private:
  /* data */

 protected:
  Prototype(/* args */);

 public:
  virtual Prototype* Clone() const = 0;
  virtual ~Prototype();
};

class ConcretePrototype:public Prototype
{
private:
    /* data */
public:
    ConcretePrototype(/* args */);
    ~ConcretePrototype();

    ConcretePrototype(const ConcretePrototype& cp);
    Prototype* Clone() const;
};

#endif //~_PROTOTYPE_H_

Prototype.cpp:

//Prototype.cpp

#include "../include/Prototype.h"
#include <iostream>

using namespace std;

Prototype::Prototype(/* args */) {}
Prototype::~Prototype() {}
Prototype* Prototype::Clone() const{
    return 0;
}

ConcretePrototype::ConcretePrototype(/* args */) {}
ConcretePrototype::~ConcretePrototype() {}
ConcretePrototype::ConcretePrototype(const ConcretePrototype& cp){
    printf("ConcretePrototype copy ... \n");
}
Prototype* ConcretePrototype::Clone() const{
    return new ConcretePrototype(*this);
}

main.cpp:

// main.cpp
#include <iostream>
#include "../include/Prototype.h"
using namespace std;

int main(int argc, char* argv[]) {
  Prototype* p = new ConcretePrototype();
  Prototype* p1 = p->Clone();
  return 0;
}

代码说明

Prototype 模式的结构和实现都很简单,其关键就是(C中)拷贝构造函数的实现方式,这也是 C实现技术层面上的事情。由于在示例代码中不涉及到层拷贝(主要指有指针、复合对象的情况),因此我们通过编译器提供的默认的拷贝构造函数(按位拷贝)的方式进行实现。说明的是这一切只是为了实现简单起见,也因为本文档的重点不在拷贝构造函数的实现技术,而在 Prototype 模式本身的思想。

编译运行结果:

patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Prototype/src$ g++ *.cpp -std=c++11
patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Prototype/src$ ./a.out 
ConcretePrototype copy ... 
patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Prototype/src$

讨论

Prototype 模式通过复制原型(Prototype)而获得新对象创建的功能,这里Prototype 本身就是“对象工厂”(因为能够生产对象),实际上 Prototype 模式和 Builder 模式、AbstractFactory 模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder 模式重在复杂对象的一步步创建(并不直接返回对象),AbstractFactory 模式重在产生多个相互依赖类的对象,而 Prototype 模式重在从自身复制自己创建新类。