原型模式 Prototype Pattern
通过一个原型对象克隆出多个一模一样的对象,该模式称之为原型模式。有时候,我们不希望反复使用类的构造函数创建许多对象,而希望从已有的对象clone,这种对象就是原型,这样的模式是原型模式。
一、介绍
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式的关键在于实现Clone()方法。Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性, 但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来 解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函 数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙 的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不 然不知道该配什么样的钥匙.
二、适用场景
(1) 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。(2) 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可以使用原型模式配合备忘录模式来实现。
(3) 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
三、UML类图
四、优缺点
4.1 优点
(1) 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。(2) 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。
(3) 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。
(4) 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。
4.2 缺点
(1) 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。
(2) 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。
(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();
}
}