一句话解释:
针对比较耗时的对象创建过程,通过原型的 Clone 方法来克隆对象,而非重新创建。
原型设计模式(Prototype Design Pattern)是一种创建型设计模式,其主要目的是通过复制已有对象来创建新的对象,而无需通过实例化类并初始化其属性。这种模式在需要创建相似对象时非常有用,尤其是当创建过程较为复杂或耗时时。
原型设计模式中的 Clone() 方法可以是深拷贝或浅拷贝,具体取决于实现的方式。
官方意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
一个比喻:(多个班级与礼堂)
多个班级需要轮流在礼堂举行活动,门口有海报标注时间,相当于礼堂对象的引用。学校不会为每个班级修一座礼堂,这样太耗时,而是每个班级共用一个礼堂,使用时按照海报的时间即可。
优缺点:
原型设计模式在合适的场景下可以提供很多优点,但在使用时需要注意克隆方法的正确性和对象的深拷贝问题。
适用场景:
实际使用场景举例:
下面例举个示例,父类实现 ICloneable 接口的 Clone() 方法:
// 父类:图形类
abstract class Shape : ICloneable // 实现接口 ICloneable 中的方法 Clone
{
protected string type;
public abstract void Draw();
public object Clone()
{
return this.MemberwiseClone(); // 创建当前对象的浅拷贝,两个引用指向同一个对象
// 注意:
// 浅拷贝就相当于给引用对象又起了另外一个名字,小黄和修勾勾都指的是这一只小狗;
// 深拷贝就是用克隆技术,把小黄复刻了一个长得一模一样的小黄二号,名字不同的同时指的对象也不同。
}
}
// 圆形类,继承图形类
class Circle : Shape
{
public Circle()
{
type = "Circle";
}
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}
// 矩形类,也继承图形类
class Rectangle : Shape
{
public Rectangle()
{
type = "Rectangle";
}
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
}
}
class Program
{
static void Main(string[] args)
{
Circle circle = new Circle(); // 创建一个圆形对象
Circle clonedCircle = (Circle)circle.Clone(); // 克隆圆形对象(复制了对象的引用)
// circle 和 clonedCircle 两个引用,指向同一个对象
clonedCircle.Draw();
Rectangle rectangle = new Rectangle(); // 创建一个矩形对象
Rectangle clonedRectangle = (Rectangle)rectangle.Clone(); // 克隆矩形对象
// rectangle 和 clonedRectangle 两个引用,指向同一个对象
clonedRectangle.Draw();
Console.ReadKey();
}
}
如下输出结果,调用克隆对象的 Draw() 得出:
根据上一章节的示例代码,简单画一个 UML 图:
Shape:原型抽象,声明一个抽象类,实现 ICloneable 接口的 Clone() 方法,使得本抽象类可以被克隆。
Circle、Rectangle:原型,继承抽象类 Shape,实现自身可被克隆的性质。
Client:创建可被克隆的原型,并通过 Clone() 方法复制原型。
例如在数据库连接管理的应用。
在数据库应用程序中,连接到数据库可能是一个耗时且资源密集的操作。为了避免每次都重新创建连接,可以使用原型设计模式来克隆现有的连接对象。
public class DbConnection : ICloneable
{
public string ConnectionString { get; set; }
// ...
public object Clone()
{
return this.MemberwiseClone();
}
}
// 使用示例:
DbConnection originalConnection = new DbConnection { ConnectionString = "..." };
DbConnection clonedConnection = (DbConnection)originalConnection.Clone();
Prorotype 和 AbstractFactory 模式在某些方面是互相竞争的。但是它们也可以一起使用,AbstractFactory 可以存储一个被克隆对象的原型集合,并且返回产品对象。
大量使用 Composite(组合) 和 Decorator(装饰) 模式的设计,通常也可以用到 Prototype 模式。