设计模式(4)——原型模式

原型模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。

浅拷贝

class Program
{
    static void Main(string[] args)
    {
        ShapePrototype shape = new RealPrototype(1);
        
        ShapePrototype real1 = shape.Clone() as RealPrototype;
        shape.Id = 2;
        Console.WriteLine("Clone1:\t" + real1.Id);
        
        ShapePrototype real2 = shape.Clone() as RealPrototype;
        Console.WriteLine("Clone2:\t" + real2.Id);
        Console.ReadLine();

    }
}

public abstract class ShapePrototype
{
    public int Id { get; set; }
    public ShapePrototype(int id)
    {
        Id = id;
    }
    
    public abstract ShapePrototype Clone();
}

public class RealPrototype : ShapePrototype
{
    public RealPrototype(int id)
        : base(id)
    { }

    public override ShapePrototype Clone()
    {
        // 调用MemberwiseClone方法实现的是浅拷贝
        return (ShapePrototype)this.MemberwiseClone();
    }
}

显示结果

Clone1:1
Clone2:2

说明拷贝成功了,修改原型没有改变拷贝的对象。
浅拷贝是指副本对象中的引用类型的数据成员与源对象的数据成员指向相同的对象。而如果是深拷贝,则必须创建整个对象的结构,副本对象中的引用类型的数据成员与源对象的数据成员指向不同的对象。

浅拷贝是容易实现的,就是使用前面提到的MemberwiseClone方法。开发人员往往希望使用的类型能够实现深拷贝,但会发现这样的类型并不 多。这种情况在System.Collections命名空间中尤其常见,这里面的类在其Clone方法中实现的都是浅拷贝。这么做主要出于两个原因:

  • 创建一个大对象的副本对性能影响较大。
  • 通用的集合类型可能会包含各种各样的对象,在这种情况下实现深拷贝并不可行,因为集合中的对象并非都是可克隆的,另外还存在循环引用的情况,这会让深拷贝过程陷入死循环。

浅拷贝的类图

在这里插入图片描述

深拷贝

对于强类型的集合情况有所不同,因为它包含的元素是可控制的,此时深拷贝变得有用,同时也是可行的。例如System.Xml.XmlNode在其Clone方法中实现了深拷贝。

class Program
{
    static void Main(string[] args)
    {
        ShapePrototype shape = new RealPrototype(new List<int>() { 1 });
        
        ShapePrototype real1 = shape.Clone() as RealPrototype;
        shape.Id[0] = 2 ;
        Console.WriteLine("Cloned1:\t" + real1.Id[0]);
        
        ShapePrototype real2 = shape.Clone() as RealPrototype;
        Console.WriteLine("Cloned2:\t" + real2.Id[0]);
        Console.ReadLine();
        
    }
}

public abstract class ShapePrototype
{
    public List<int> Id = new List<int>();
    public ShapePrototype()
    {
    }
    
    public abstract ShapePrototype Clone();
}

public class RealPrototype : ShapePrototype
{
    
    public RealPrototype(List<int> id)
        : base()
    {
        foreach (int e in id)
        {
            Id.Add(e);
        }
    }
    
    public override ShapePrototype Clone()
    {
        return new RealPrototype(Id);
        // 调用MemberwiseClone方法实现的是浅拷贝
        //return (ShapePrototype)this.MemberwiseClone();
    }
}

显示结果

Clone1:1
Clone2:2

虽然结果还是这个,但实际上把Clone方法里注释的那句话改为:

public override ShapePrototype Clone()
{
    //return new RealPrototype(Id);
    // 调用MemberwiseClone方法实现的是浅拷贝
    return (ShapePrototype)this.MemberwiseClone();
}

显示结果

Clone1:2
Clone2:2

深拷贝的类图

在这里插入图片描述

标题.NET中原型模式的实现

在.NET中可以很容易地通过实现ICloneable接口(这个接口就是原型,提供克隆方法,相当于与上面代码中ShapePrototype抽象类)中Clone()方法来实现原型模式,如果我们想我们自定义的类具有克隆的功能,首先定义类继承与ICloneable接口并实现Clone方法。

改为本例就是这样:

class Program
{
    static void Main(string[] args)
    {
        ShapePrototype shape = new ShapePrototype(new List<int>() { 1 });
        
        ShapePrototype real1 = shape.Clone() as ShapePrototype;
        shape.Id[0] = 2 ;
        Console.WriteLine("Cloned1:\t" + real1.Id[0]);
        
        ShapePrototype real2 = shape.Clone() as ShapePrototype;
        Console.WriteLine("Cloned2:\t" + real2.Id[0]);
        Console.ReadLine();
        
    }
}
public class ShapePrototype : ICloneable
{
    public List<int> Id = new List<int>();
    public ShapePrototype(List<int> id)
    {
        foreach (int e in id)
        {
            Id.Add(e);
        }
    }

    public object Clone()
    {
        return new ShapePrototype(Id);
    }
}

优点和缺点

原型模式的优点:

  • 原型模式向客户隐藏了创建新实例的复杂性
  • 原型模式允许动态增加或较少产品类。
  • 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
  • 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构

原型模式的缺点:

  • 每个类必须配备一个克隆方法
  • 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

本文主要借鉴了《Gof设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值