【23种设计模式】创建型模式 > 原型模式

原型模式 Prototype Pattern 

通过一个原型对象克隆出多个一模一样的对象,该模式称之为原型模式。有时候,我们不希望反复使用类的构造函数创建许多对象,而希望从已有的对象clone,这种对象就是原型,这样的模式是原型模式。

一、介绍

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式的关键在于实现Clone()方法。Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性, 但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来 解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函 数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙 的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不 然不知道该配什么样的钥匙. 

二、适用场景

(1) 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。
(2) 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可以使用原型模式配合备忘录模式来实现。
(3) 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。

三、UML类图


四、优缺点

4.1 优点

(1) 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
(2) 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。
(3) 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。
(4) 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。

4.2 缺点

(1) 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。
(2) 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。

五、代码实现

下面的代码从一个实例Clone出另一个实例。原型类是一个抽象类或者接口,派生类必须实现Clone()接口。

C++ 

#include <iostream>
using namespace std; 

// 原型
class Prototype
{
public :
    Prototype() {}; 
    virtual ~Prototype() { };
    virtual Prototype* clone() = 0;
};

// 派生自Prototype,实现Clone方法
class ConcreatePrototype_A : public Prototype
{
public:
    ConcreatePrototype_A() {};
    // 复制构造函数
    ConcreatePrototype_A(const ConcreatePrototype_A& a)
    {
        // 做一些赋值的工作
    }
    // 实现Clone()
    Prototype* clone()
    {
        // 调用复制构造函数
        return new ConcreatePrototype_A(*this);
    }
};

// 派生自Prototype,实现Clone方法
class ConcreatePrototype_B : public Prototype
{
public:
    ConcreatePrototype_B() {};
    // 复制构造函数
    ConcreatePrototype_B(const ConcreatePrototype_B& a)
    {
        // 做一些赋值的工作
    }
    Prototype* clone()
    {
        // 调用复制构造函数
        return new ConcreatePrototype_B(*this);
    }
};

int main()
{
    Prototype* p = new ConcreatePrototype_A(); 
    Prototype* p_clone = p->clone(); // clone 的是 ConcreatePrototype_A 类型的实例p的副本

    delete p; 
    delete p_clone;

    p = new ConcreatePrototype_B();
    p_clone = p->clone(); // clone 的是 ConcreatePrototype_B 类型的实例p的副本

    delete p;
    delete p_clone;
}
C# 

using System;
using System.Collections.Generic;
class Program
{
    abstract class Prototype 
    {
        public abstract Prototype Clone(); 
    }

    class ConcreatePrototype_A : Prototype
    {
        public ConcreatePrototype_A()
        {
        }

        public ConcreatePrototype_A(ConcreatePrototype_A a)
        {
            // 做一些赋值工作
        }

        public override Prototype Clone()
        {
            return new ConcreatePrototype_A(this);
        }
    }

    class ConcreatePrototype_B : Prototype
    {
        public ConcreatePrototype_B()
        {
        }

        public ConcreatePrototype_B(ConcreatePrototype_B a)
        {
            // 做一些赋值工作
        }

        public override Prototype Clone()
        {
            return new ConcreatePrototype_B(this);
        }

    }

    public static void Main()
    {
        Prototype p = new ConcreatePrototype_A();
        Prototype  p_clone = p.Clone();
        p = new ConcreatePrototype_B();
        p_clone = p.Clone();
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值