C++原型模式

简述

原型模式(Prototype Pattern)是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,而无需知道任何创建的细节。

  • 简述
  • 模式结构
  • 优缺点
  • 适用场景
  • 案例分析
  • 代码实现

版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820

模式结构



UML 结构图:

  • 抽象原型(Prototype):定义了克隆自身的接口。
  • 具体原型(ConcretePrototype):被复制的对象,需要实现 Prototype 定义的接口。

优缺点



优点:

  • 如果创建新的对象比较复杂,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
  • 简化对象的创建,无需理会创建过程。
  • 可以在程序运行时(对象属性发生了变化)获得一份内容相同的实例,他们之间不会相互干扰。

缺点:

  • 在实现深拷贝时可能需要比较复杂的代码
  • 需要为每一个类配备一个克隆方法,而且该克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了“开闭原则”。

适用场景


  • 如果创建新对象成本较大,可以利用已有的对象进行复制来获得。
  • 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
  • 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。

案例分析


你挑着担 我牵着马
迎来日出 送走晚霞
……
敢问路在何方 路在脚下
敢问路在何方 路在脚下

一首《敢问路在何方》,触动了无数人的心弦。当年只要前奏一响,小伙伴们就再也把持不住了。。。《西游记》作为四大名著之一,可谓是家喻户晓,神一样的存在。从小到大,更是百看不厌。

记得孙悟空在打黄风怪、收七狮的时候,会拔一根猴毛,幻化为成千上万个孙悟空(猴哥、猴哥,你真了不得)。。。原型模式亦是如此,同样提供了自我复制功能。

注: 《西游记》中记载:孙悟空本是花果山上一块仙石所生,天地生成,无父母,无名无姓,拜菩提祖师处,得名孙悟空。

PS: 示例中的抽象原型为猴子(Monkey)类,而非仙石类,千万不要一脸懵逼!

代码实现



创建抽象原型

定义一个猴子类 Monkey,并提供一个 Clone() 接口,用于自我复制。

// prototype.h
#ifndef PROTOTYPE_H
#define PROTOTYPE_H

// 猴子
class Monkey
{
public:
    Monkey(){}
    virtual ~Monkey(){}
    virtual Monkey* Clone() = 0;  // 克隆
    virtual void Play() = 0;  // 玩耍
};

#endif // PROTOTYPE_H

创建具体原型

美猴王腾空出世:

// concrete_prototype.h
#ifndef CONCRETE_PROTOTYPE_H
#define CONCRETE_PROTOTYPE_H

#include "prototype.h"
#include <iostream>
#include <string>

using namespace std;

// 孙悟空
class SunWuKong : public Monkey
{
public:
    SunWuKong(string name){ m_strName = name; }
    ~SunWuKong(){}

    // 拷贝构造函数
    SunWuKong(const SunWuKong &other) {
        m_strName = other.m_strName;
    }
    Monkey* Clone() {
        // 调用拷贝构造函数
        return new SunWuKong(*this);
    }
    void Play() {
        cout << m_strName << " play Golden-Hoop-Stick" << endl;
    }

private:
    string m_strName;
};

#endif // CONCRETE_PROTOTYPE_H

同样是猴子,别的猴子玩的是 LOL,而孙悟空玩的是金箍棒(Golden-Hoop-Stick),谁要他是齐天大圣呢!

创建客户端

拔一根猴毛,吹出猴万个:

// main.cpp
#include "concrete_prototype.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif

int main()
{
    // 孙悟空
    Monkey *pSWK = new SunWuKong("Qi Tian Da Sheng");

    // 克隆猴子猴孙
    Monkey *pSWK1 = pSWK->Clone();
    Monkey *pSWK2 = pSWK1->Clone();

    pSWK1->Play();
    pSWK2->Play();

    SAFE_DELETE(pSWK1);
    SAFE_DELETE(pSWK2);
    SAFE_DELETE(pSWK);

    getchar();

    return 0;
}

输出如下:

Qi Tian Da Sheng play Golden-Hoop-Stick
Qi Tian Da Sheng play Golden-Hoop-Stick

除了孙悟空以外,我们还可以创建六耳猕猴,其实力和孙悟空一般无二,两者大战,闹的天翻地覆。。。真是快哉!

时间: 2024-10-31 02:35:54

C++原型模式的相关文章

设计模式之原型模式

一.引入 小菜的问题:要把简历发到多家公司,简历的份数就必须足够. 大鸟的回答:用编程来复制自己简历. 二.解决过程 ① 最初的写法:  简历类: <span style="font-family:KaiTi_GB2312;font-size:24px;">class Resume { private string name; private string sex; private string age; private string timeArea; private s

JavaScript设计模式系列之原型模式

prototype模式通过实例对象指定需要创建的类型,这与factory method模式有本质不同,factory method模式是通过类的继承定义不同子类来达到创建不同类型对象的目的,属于类模式,prototype模式通过调用组合的对象成员生成不同类型的对象实例,属于对象模式. 由于这个特性,prototype具有以下适用场合: · 需要运行时确定实例化的类时,比如动态装载库时 · 避免创建过多子类时.子类太多永远是不受欢迎的,在factory method中我们也提到通过模板或者参数化来

javascript创建对象之原型模式(三)

先上代码: function Human() { }         Human.prototype.name = "成吉思汗";         Human.prototype.sex = "男";         Human.prototype.say = function () {             alert(this.name);         }         var man = new Human();         man.say();

javascript创建对象之函数构造模式和原型模式结合使用(四)

创建自定义类型的常见方式就是组合使用构造函数模式与原型模式一起使用. 构造函数模式用于定义实例对象的特有的部分(属性和方法),原型模式用于定义共享的部分. 这样最大限度的节省了内存的开销. function Human(name, sex) {             this.name = name;             this.sex = sex;             this.getWife=function(){//娶老婆                 if (this.se

javascript创建对象之动态原型模式(五)

动态原型模式是将所有的信息都封装到工造函数中,而构造函数中初始化原型,有保持了同时在使用构造函数和原型的优点. function Human(name, sex) {             this.name = name;             this.sex = sex;             if (typeof this.say != "function") {                 Human.prototype.say = function () {   

Javascript实例教程:使用动态原型模式

文章简介:使用动态原型模式时,不能使用对象字面量重写原型.前面已经解释过了,如果在已经创建了实例的情况系重写原型,那么就会切断现有实例与新原型之间的联系. 有其它OO语言经验的开发人员在看到独立的构造函数和原型时,很可能会感到非常的困惑.动态原型模式正是致力于解决这个问题的一个方案,它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点.换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型.来看一个例子: f

Javascript教程:组合使用构造函数模式和原型模式

文章简介:创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式.构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性.结果,每个实例都会有自己的一份实例属性的副本.但同时又共享着对方法的引用,最大限度的节省了内存.另外这种模式还支持向构造函 创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式.构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性.结果,每个实例都会有自己的一份实例属性的副本.但同时又共享着对方法的引用,最大限度的节省了内存.另外这种模式还

java设计模式---prototype(原型)模式

设计 java设计模式---prototype(原型)模式 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.      Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,      工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求      原型对象拷贝它们自己来实施创建.      适用性:当要实例化的类是在运行时刻指定时,例如,通过动态装载:或者  为了避免创建一个与产品类层次平行的工厂类层

php设计模式 Prototype (原型模式)代码

复制代码 代码如下:<?php /** * 原型模式 * * 用原型实例指定创建对象的种类.并且通过拷贝这个原型来创建新的对象 * */ abstract class Prototype { private $_id = null; public function __construct($id) { $this->_id = $id; } public function getID() { return $this->_id; } public function __clone() /

一番话--原型模式

今天来晚了,因为公司周一很多事情要做,而我昨天晚上没有睡好,来了以后什么事情没做先睡了一个上午.:(幸好老板在开会hiahia.不过下次就没有这么幸运了,要是有孙猴子的分身法,随便克隆一个我放在那里干活儿,我睡觉多好呀....所以今天就介绍一下原型模式(prototype)有时候,我们所要创建的对象大致上都很相似,只是在部分属性的值上有所区别,而且,他们的初始化过程相对来说比较复杂,需要耗费一定的时间,那么我们可以使用原型模式.首先初始化一个一个类的一个实例,然后其他的实例通过对第一个实例的克隆