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

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

类型创建型模式。

类图

 

参与角色

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

另外实现其他接口。

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

概述:

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

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

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

代码:

// 提供接口

class CPrototype
{
public:
    virtual CPrototype* Clone() = 0;
    virtual void Show() = 0;
    virtual void SetRam(int _nRam) = 0;
    virtual void SetRom(int _nRom) = 0;
};

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

class CComputerConfig : public CPrototype
{
public:
    CComputerConfig(char* _szName, int _nRomSize, int _nRamSize) : m_nRomSize(_nRomSize), m_nRamSize(_nRamSize)
    {
        if (NULL != _szName)
        {
            size_t nSize = strlen(_szName) + 1;
            m_szComputerName = new char[nSize];
            strcpy_s(m_szComputerName, nSize, _szName);
        }
        else
        {
            m_szComputerName = NULL;
        }
    }

    ~CComputerConfig()
    {
        if (NULL != m_szComputerName)
        {
            delete m_szComputerName;
        }
    }

    CComputerConfig(const CComputerConfig& _other)
    {
        if (NULL == _other.m_szComputerName)
        {
            m_szComputerName = NULL;
        }
        else
        {
            size_t nSize = strlen(_other.m_szComputerName) + 1;
            m_szComputerName = new char[nSize];
            strcpy_s(m_szComputerName, nSize, _other.m_szComputerName);

            m_nRomSize = _other.m_nRomSize;
            m_nRamSize = _other.m_nRamSize;
        }
    }

    virtual CPrototype* Clone()
    {
        return new CComputerConfig(*this);
    }

    virtual void Show()
    {
        cout<<m_szComputerName<<",Ram "<<m_nRamSize<<",Rom "<<m_nRomSize<<endl;
    }

    virtual void SetRam(int _nRam)
    {
        m_nRamSize = _nRam;
    }

    virtual void SetRom(int _nRom)
    {
        m_nRomSize = _nRom;
    }
public:
    char* m_szComputerName;
    int m_nRomSize;
    int m_nRamSize;
};

// 客户端

int _tmain(int argc, _TCHAR* argv[])
{
    // ThindPad系列电脑
    CComputerConfig computer("Thinkpad", 500, 2);

    // 原型
    CPrototype* pPrototype = &computer;
    pPrototype->Show();

    // ThindPad系列的2G内存版,500G硬盘版
    CPrototype* p2GComputer = computer.Clone();
    p2GComputer->SetRam(4);
    p2GComputer->Show();

    // 4G内存,1T硬盘版
    CPrototype* p1TCompter = computer.Clone();
    p1TCompter->SetRam(8);
    p1TCompter->SetRom(1024);
    p1TCompter->Show();

	return 0;
}

使用场合

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

优缺点

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

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

参考资料

  1. 《设计模式——可复用面向对象软件基础》
  2. 《Java与模式》
  3. 《大话设计模式》
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值