• 设计模式6——创建型模式之原型模式


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

    类型:创建型模式。

    类图

     

    参与角色:

    1. CPrototype,抽象原型基类,提供一个Clone的接口以及一些设置显示的接口。
    1. CConcretePrototype,声明定义原型的相关参数,并实现Clone接口,主要是通过实现拷贝构造函数来完成的。

    另外实现其他接口。

    1. Client,首先定义一个原型对象,然后以此为原型克隆新的对象。

    概述:

            如果只是为了更快的完成新对象的生成,其实就没必要使用原型模式了。因为可以直接使用拷贝构造函数即可。而使用原型模式最重要的原因是隔离Client去了解具体的实现类,降低模块间的耦合。Client只需要知道一个抽象类的指针,不仅可以操作具体各咱方法,另外也还可以生成新的对象。

            另外,使用拷贝构造函数时,需要注意深拷贝及浅拷贝。浅拷贝,即按位进行拷贝,即两个对象的每一个成员变量是相同的。深拷贝,自定义拷贝,一般会处理指针,引用等类型,保证它们有相同的值,而不是它们本身相同。

            有一批Thinkpad电脑,除了内存和硬盘容量外,其他配置都相同。我们可以通过原型对象生成新的对象,并且不需要知道具体的实现类名。

    // 提供接口

     1 class CPrototype
     2 
     3 {
     4 
     5 public:
     6 
     7     virtual CPrototype* Clone() = 0;
     8 
     9     virtual void Show() = 0;
    10 
    11     virtual void SetRam(int _nRam) = 0;
    12 
    13     virtual void SetRom(int _nRom) = 0;
    14 
    15 };

    // 电脑的基本配置信息类

      1 class CComputerConfig : public CPrototype
      2 
      3 {
      4 
      5 public:
      6 
      7     CComputerConfig(char* _szName, int _nRomSize, int _nRamSize) : m_nRomSize(_nRomSize), m_nRamSize(_nRamSize)
      8 
      9     {
     10 
     11         if (NULL != _szName)
     12 
     13         {
     14 
     15             size_t nSize = strlen(_szName) + 1;
     16 
     17             m_szComputerName = new char[nSize];
     18 
     19             strcpy_s(m_szComputerName, nSize, _szName);
     20 
     21         }
     22 
     23         else
     24 
     25         {
     26 
     27             m_szComputerName = NULL;
     28 
     29         }
     30 
     31     }
     32 
     33  
     34 
     35     ~CComputerConfig()
     36 
     37     {
     38 
     39         if (NULL != m_szComputerName)
     40 
     41         {
     42 
     43             delete m_szComputerName;
     44 
     45         }
     46 
     47     }
     48 
     49  
     50 
     51     CComputerConfig(const CComputerConfig& _other)
     52 
     53     {
     54 
     55         if (NULL == _other.m_szComputerName)
     56 
     57         {
     58 
     59             m_szComputerName = NULL;
     60 
     61         }
     62 
     63         else
     64 
     65         {
     66 
     67             size_t nSize = strlen(_other.m_szComputerName) + 1;
     68 
     69             m_szComputerName = new char[nSize];
     70 
     71             strcpy_s(m_szComputerName, nSize, _other.m_szComputerName);
     72 
     73  
     74 
     75             m_nRomSize = _other.m_nRomSize;
     76 
     77             m_nRamSize = _other.m_nRamSize;
     78 
     79         }
     80 
     81     }
     82 
     83  
     84 
     85     virtual CPrototype* Clone()
     86 
     87     {
     88 
     89         return new CComputerConfig(*this);
     90 
     91     }
     92 
     93  
     94 
     95     virtual void Show()
     96 
     97     {
     98 
     99         cout<<m_szComputerName<<",Ram "<<m_nRamSize<<",Rom "<<m_nRomSize<<endl;
    100 
    101     }
    102 
    103  
    104 
    105     virtual void SetRam(int _nRam)
    106 
    107     {
    108 
    109         m_nRamSize = _nRam;
    110 
    111     }
    112 
    113  
    114 
    115     virtual void SetRom(int _nRom)
    116 
    117     {
    118 
    119         m_nRomSize = _nRom;
    120 
    121     }
    122 
    123 public:
    124 
    125     char* m_szComputerName;
    126 
    127     int m_nRomSize;
    128 
    129     int m_nRamSize;
    130 
    131 };
    132 
    133  

    // 客户端

     1 int _tmain(int argc, _TCHAR* argv[])
     2 
     3 {
     4 
     5     // ThindPad系列电脑
     6 
     7     CComputerConfig computer("Thinkpad", 500, 2);
     8 
     9  
    10 
    11     // 原型
    12 
    13     CPrototype* pPrototype = &computer;
    14 
    15     pPrototype->Show();
    16 
    17  
    18 
    19     // ThindPad系列的2G内存版,500G硬盘版
    20 
    21     CPrototype* p2GComputer = computer.Clone();
    22 
    23     p2GComputer->SetRam(4);
    24 
    25     p2GComputer->Show();
    26 
    27  
    28 
    29     // 4G内存,1T硬盘版
    30 
    31     CPrototype* p1TCompter = computer.Clone();
    32 
    33     p1TCompter->SetRam(8);
    34 
    35     p1TCompter->SetRom(1024);
    36 
    37     p1TCompter->Show();
    38 
    39  
    40 
    41 return 0;
    42 
    43 }
    44 
    45  

    使用场合

    1. 两个模块A,B,模块B对外暴露一个对象C指针。而模块A需要建立很多很多C的对象,但是不需要知道具体的C是如何创建的。这个时候就应该使用原型模式。

    优缺点

    1. 优点,能够降低模块间的耦合性,另外能够快速的创建新对象。

    缺点,改造一个已有类型时,需要细心考虑所有成员变量拷贝的问题,容易遗漏造成错误。

    参考资料

    1. 《设计模式——可复用面向对象软件基础》
    2. 《Java与模式》
    3. 《大话设计模式》
  • 相关阅读:
    NIFI简介
    STM32L4R9xxxx图形加速器DMA2D实例使用——32位带alpha透明通道的位图ARGB8888显示时地址对齐问题
    25、如何计算车辆的出车次数?
    26、计算每年每月每天的数据
    11、【打印】打印发票—如何在页面合适地打印发票?
    12、如何将pdf改成word文档呢?
    2、如何设置签名?
    1、outlook邮箱如何撤回邮件?
    【其他】在洛谷上的最优解记录
    【笔记】积性函数、莫比乌斯反演
  • 原文地址:https://www.cnblogs.com/feihe0755/p/3513788.html
Copyright © 2020-2023  润新知