原型模式

1.概述

  原型模式就是通过复制现在已经存在的对象来创建一个新的对象。

  工作原理:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。

 

2.角色

  客户(Client)角色:客户端类向原型管理器提出创建对象的请求。

  抽象原型(Prototype)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体原型类所需的接口。

  具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

  原型管理器(Prototype Manager)角色:创建具体原型类的对象,并记录每一个被创建的对象。

 

3优缺点

 优点:

  1)允许动态地增加或减少产品类。且增加新产品对整个结构没有影响。

  2)提供简化的创建结构。工厂方法常需要有一个与产品类相同的等级结构,而原型模式不需要。

  3)产品类不需要非得有任何事先确定的等级结构,因为原型模式适用于任何的等级结构。

 缺点:

  1) 每一个类必须配备一个克隆方法。

 

  浅复制和深复制

  浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。

  深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.

 

4 与new的区别

  有的时候,创建实例的构造函数非常的复杂,在执行这个构造函数时会消耗较长的时间,同时,这个构造函数中的一些信息又没有什么变化

那么直接使用 new 来创建这样一个实例就显得太昂贵了。这时候就可以使用原型模式。

 

5. 使用场景

  以下的几个场景的时候,可能使用原型模式更简单也效率更高。

  1)当一个系统应该独立于它的产品创建、构成和表示时。

  2)当要实例化的类是在运行时刻指定时,例如,通过动态装载。

  3)为了避免创建一个与产品类层次平行的工厂类层次时。

  4)当一个类的实例只能有几个不同状态组合中的一种时。

  比如在画图工具里,要画圆只需要拖动工具条的画圆工具到绘图区即可,而不需要从头开始一点一点的画一个圆,而且如果需要不同大小和颜色的圆,只需要复制几个圆,然后再修改他们的大小和颜色即可。

 

6.代码实现

1)不带原型管理器

http://blog.csdn.net/wuzhekai1985/article/details/6667020

 1 class Resume
 2 {
 3 protected:
 4     char *name;
 5 public:
 6     virtual Resume* Clone(){return NULL;}
 7     virtual void Set(char *n){}
 8     virtual void Show(){}
 9 };
10 
11 class ResumeA: public Resume
12 {
13 public:
14     ResumeA(const char *str)
15     {
16         if(str == NULL) 
17         {
18             name = new char[1];
19             name[0] = '\0';
20         }
21         else
22         {
23             name = new char[strlen(str)+1];
24             strcpy(name, str);
25         }
26     }//构造函数
27     ResumeA(const ResumeA &r)
28     {
29         name = new char[strlen(r.name)+1];
30         strcpy(name, r.name);
31     }//拷贝构造函数
32     ResumeA* Clone()
33     {
34         return new ResumeA(*this);
35     }
36     void Show()
37     {
38         cout<<"ResumeA name : "<<name<<endl;
39     }
40 };
41 
42 
43 class ResumeB: public Resume
44 {
45 public:
46     ResumeB(const char *str)
47     {
48         if(str == NULL) 
49         {
50             name = new char[1];
51             name[0] = '\0';
52         }
53         else
54         {
55             name = new char[strlen(str)+1];
56             strcpy(name, str);
57         }
58     }//构造函数
59     ResumeB(const ResumeB &r)
60     {
61         name = new char[strlen(r.name)+1];
62         strcpy(name, r.name);
63     }//拷贝构造函数
64     ResumeB* Clone()
65     {
66         return new ResumeB(*this);
67     }
68     void Show()
69     {
70         cout<<"ResumeB name : "<<name<<endl;
71     }
72 };
73 
74 
75 int main()
76 {
77     Resume *r1 = new ResumeA("A");    
78     Resume *r2 = new ResumeB("B");    
79     Resume *r3 = r1->Clone();    
80     Resume *r4 = r2->Clone();    
81     r1->Show(); r2->Show();    
82     //删除r1,r2    
83     delete r1; delete r2;       
84     r1 = r2 = NULL;    
85     //深拷贝所以对r3,r4无影响    
86     r3->Show(); r4->Show();    
87     delete r3; delete r4;    
88     r3 = r4 = NULL;  
89 }
90 
91     

2)带原型管理器
只需在原有的代码中添加原型管理器代码即可

http://blog.csdn.net/lcl_data/article/details/8764228

#pragma once
#include "stdafx.h"
#include <iostream>
#include<vector> 
using namespace std;


class Resume
{
protected:
    char *name;
public:
    virtual Resume* Clone(){return NULL;}
    virtual void Set(char *n){}
    virtual void Show(){}
};

class ResumeA: public Resume
{
public:
    ResumeA(const char *str)
    {
        if(str == NULL) 
        {
            name = new char[1];
            name[0] = '\0';
        }
        else
        {
            name = new char[strlen(str)+1];
            strcpy(name, str);
        }
    }//构造函数
    ResumeA(const ResumeA &r)
    {
        name = new char[strlen(r.name)+1];
        strcpy(name, r.name);
    }//拷贝构造函数
    ResumeA* Clone()
    {
        return new ResumeA(*this);
    }
    void Show()
    {
        cout<<"ResumeA name : "<<name<<endl; 
    }
};


class ResumeB: public Resume
{
public:
    ResumeB(const char *str)
    {
        if(str == NULL) 
        {
            name = new char[1];
            name[0] = '\0';
        }
        else
        {
            name = new char[strlen(str)+1];
            strcpy(name, str);
        }
    }//构造函数
    ResumeB(const ResumeB &r)
    {
        name = new char[strlen(r.name)+1];
        strcpy(name, r.name);
    }//拷贝构造函数
    ResumeB* Clone()
    {
        return new ResumeB(*this);
    }
    void Show()
    {
        cout<<"ResumeB name : "<<name<<endl; 
    }
};

class ResumeManager
{
private:
    vector<Resume *> mResume;
public:
    ResumeManager(){}
    void add(Resume* resume)
    {
        mResume.push_back(resume);
    }

    Resume *get(int index) const
    {
        assert(index>=0 && index<mResume.size());
        return mResume[index];
    }
};

int main()
{
    ResumeManager *manager = new ResumeManager();
    Resume *r1 = new ResumeA("A");
    Resume *r2 = new ResumeB("B");
    manager->add(r1);
    manager->add(r2);
    manager->get(0)->Show();
    manager->get(1)->Show();
    Resume *r3 = manager->get(0)->Clone();
    Resume *r4 = manager->get(1)->Clone();
    //删除r1,r2
    delete r1; delete r2;
    r1 = r2 = NULL;
    //深拷贝所以对r3,r4无影响
    r3->Show(); r4->Show();
    delete r3; delete r4;
    r3 = r4 = NULL;
}

3)子类转换为父类的方式
《大话设计模式C++版》

#include<iostream>
#include <vector>
#include <string>
using namespace std;

//抽象基类
class Prototype  
{ 
private:
string m_strName;
public: 
    Prototype(string strName){ m_strName = strName; }
    Prototype() { m_strName = " "; }
    void Show() 
    {
        cout<<m_strName<<endl;
    }
    virtual Prototype* Clone() = 0 ; 
} ; 

// class ConcretePrototype1 
class ConcretePrototype1 : public Prototype 
{ 
public: 
    ConcretePrototype1(string strName) : Prototype(strName){}
    ConcretePrototype1(){}

virtual Prototype* Clone() 
    { 
        ConcretePrototype1 *p = new ConcretePrototype1() ; 
        *p = *this ;                         //复制对象 
        return p ; 
    } 
} ; 

// class ConcretePrototype2 
class ConcretePrototype2 : public Prototype 
{ 
public: 
    ConcretePrototype2(string strName) : Prototype(strName){}
    ConcretePrototype2(){}

    virtual Prototype* Clone() 
    { 
        ConcretePrototype2 *p = new ConcretePrototype2() ; 
        *p = *this ; //复制对象 
        return p ; 
    } 
} ; 

//客户端
int main()
{
    ConcretePrototype1* test = new ConcretePrototype1("小王");
    ConcretePrototype2* test2 = (ConcretePrototype2*)test->Clone();
    test->Show();
    test2->Show();
    return 0;
}

 

posted on 2015-01-26 17:55  306573704  阅读(216)  评论(0编辑  收藏  举报

导航