zoukankan      html  css  js  c++  java
  • 原型模式

    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] = '';
    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] = '';
    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] = '';
            }
            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] = '';
            }
            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;
    }
  • 相关阅读:
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
    SharePoint 打开文档附件不弹出提示框
    SharePoint2010 安装时报“未能启动数据库服务 MSSQL$Sharepoint"解决办法
    常见问题
    sharepoint 关于pdf格式在线打开
    ASP.NET 2.0 连接Sql Server 2005报错 [DBNETLIB][ConnectionOpen (Invalid Instance()).]无效的连线。
    <转>SQL Server 2008 R2十大新特性解析
    windows查看端口占用情况
    SQL Server适用脚本收集一
    信息系统中用户的域AD认证功能
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4250938.html
Copyright © 2011-2022 走看看