定义
使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
原型模式是一种对象创建型模式,它的工作原理很简单:将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程。由于在软件系统中经常会遇到需要创建多个相同或者相似对象的情况
需要注意的是,通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常,对克隆所产生的对象进行修改对原型对象不会造成任何影响,每一个克隆对象都是相互独立的。
浅克隆与深克隆
浅克隆
在浅克隆中,如果原型对象的成员变量是值类型(如int , double,byte, bool,char等基本数据类型),将复制一份给克隆对象﹔如果原型对象的成员变量是引用类型(如类、接口,数组等复杂数据类型),则将引用对象的地址复制一份给克隆对象,也就是说,原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制
深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将被复制
结构
- (1)
Prototype
(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类也可以是接口,甚至可以是具体实现类。 - (2)
ConcretePrototype
(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。 - (3)
Client
(用户类):在用户类中,让一个原型对象克隆自身从而创建一个新的对象,只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。
实现
1.通用的方法
通用的克隆实现方法是在具体原型类的克隆方法中创建一个与自身类型相同的对象并将其返回,是创建的同时将相关参数传入新创建的对象中,保证它们的成员变量相同。
abstract class Prototype
{
public abstract Prototype Clone();
}
class ConcretePrototype:Prototype
{
private string attr; //成员变量
public string Attr
{
get { return attr; }
set { attr = value; }
}
public override Prototype Clone()
{
ConcretePrototype prototype = new ConcretePrototype();
prototype.Attr = attr;
return prototype;
}
}
class Program
{
static void Main(string[] args)
{
ConcretePrototype prototype = new ConcretePrototype();
ConcretePrototype copy = (ConcretePrototype)prototype.Clone();
}
}
2.C#中的MemberwiseClone()方法和ICloneable接口
在C#语言中,提供了一个MemberwiseClone()
方法用于实现浅克隆,该方法使用起来很方便,直接调用一个已有对象的MemberwiseClone()
方法即可实现克隆。
MemberwiseClone()
//成员类
class Member
{
}
class ConcretPrototypeA
{
private Member member;
public Member Member
{
get { return member; }
set { member = value; }
}
//克隆方法
public ConcretPrototypeA Clone()
{
return (ConcretPrototypeA)this.MemberwiseClone(); //浅克隆
}
}
class Program
{
static void Main(string[] args)
{
ConcretPrototypeA prototype, copy;
prototype = new ConcretPrototypeA();
copy = prototype.Clone();
}
}
ICloneable接口
//成员类
class Member
{
}
class ConcretePrototypeB : ICloneable
{
private Member member;
public Member Member
{
get { return member; }
set { member = value; }
}
public object Clone()
{
ConcretePrototypeB copy = (ConcretePrototypeB)this.MemberwiseClone(); //深克隆
Member newMember = new Member();
copy.Member = newMember;
return copy;
}
}
class Program
{
static void Main(string[] args)
{
ConcretePrototypeB prototype, copy;
prototype = new ConcretePrototypeB();
copy = (ConcretePrototypeB)prototype.Clone();
}
}
优点
- (1)简化创建过程
- (2)扩展性较好
- (3)可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(例如恢复到某一历史状态),可辅助实现撤销操作。
缺点
- (1)需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了开闭原则。
- (2)在实现深克隆时需要编写较为复杂的代码,实现起来比较麻烦