包你懂设计模式之:原型模式(Prototype Pattern)

原型模式属于创建型的设计模式,也是我设计模式系列中最后一个创建型的设计模式,之前的创建型模式有:简单工厂、工厂方法、抽象工厂、建造者模式、单例模式,直接点击查看。

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的实例。原先实例化对象一般用new关键字,或者用前面的提到的设计模式来获取实例。而原型模式给我们一种前所未有的全新体验,它不用去创建实例,不管实例化的过程多么复杂,完全不关心,只要有一个现成的实例就行,复制粘贴搞定。对象的实例在内存中存储,通过copy对应的这块内存区域能得到新的实例,而且效率非常高,在我们需要大量实例的时候,这个模式能够很好的提升性能。

魂斗罗都玩过吧,一场游戏下来杀人(小怪)无数。抽象到我们的代码里面,这些小怪就是一个个小怪对象的实例,传统方式一百个小怪就要实例化100次,如果创建小兵的逻辑复杂或者代价比较高那就更加麻烦了,这种情况下,我们的原型模式就可以大展拳脚了。拿一个小怪作为原型,复制粘贴得到打不完的小怪。

=====================小怪类==========================

/// <summary>
/// 小怪对象 实现ICloneable 接口中就一个Clone方法
/// </summary>
public class Monster : ICloneable
{
public Monster()
{
Console.WriteLine("我被实例化了。。。。。");
}
//编号
public string MonsterType { get; set; }
//生命值
public int HealthValue { get; set; }
//伤害值
public int ForceValue { get; set; }

//攻击
public void MonsterAttribute()
{
Console.WriteLine($"编号:{MonsterType},\t生命值:{HealthValue} ,\t伤害值:{ForceValue} ");
}
//实现接口方法,返回一个object对象
public object Clone()
{
//内置的MemberwiseClone()方法,完成对象的拷贝
return this.MemberwiseClone();
}
}

 上面代码的核心就是继承了ICloneable 接口并实现了Clone()方法。在客户端我们就可以使用Clone()方法来获取复制后的新对象。

=====================客户端==========================

static void Main(string[] args)
{
Monster monster = new Monster() {MonsterType = "垃圾小怪",HealthValue = 100,ForceValue=100};
monster.MonsterAttribute();

Monster monster1 = (Monster)monster.Clone();
monster1.MonsterType = "普通小怪";
monster1.HealthValue = 200;
monster1.ForceValue = 300;
monster1.MonsterAttribute();

Monster monster2 = (Monster)monster.Clone();
monster2.MonsterType = "进阶怪物";
monster2.HealthValue = 500;
monster2.ForceValue = 600;
monster2.MonsterAttribute();

Console.ReadLine();
}

=====================结果==========================

包你懂设计模式之:原型模式(Prototype Pattern)

从上面运行的结果看来,小怪对象只被实例化了一次,但是我们得到了三个小兵的实例,这就是原型模式的简单应用。但是还没完,原型模式有浅复制和深复制,上面只是浅复制。

MemberwiseClone()方法是这样的:复制的时候如果遇到对象的成员是值类型,则直接把值复制过来,如果字段是引用类型,则复制引用地址,而目标地址上的值不会被复制,因此 复制来的实例 的 引用类型成员 和 原型 的 引用类型成员是指向同一对象的。下面我们通过修改Monster类,来说明下这个情况:

=====================修改后的小怪类==========================

public class Monster : ICloneable
{
public Monster()
{
Console.WriteLine("我被实例化了。。。。。");
}
//编号
public string MonsterType { get; set; }

//***********这边将原先的两个字段合并到一个属性类种,产生一个引用类型的字段***************//
public MonsterAttribute MonsterAttribute { get; set; }
//攻击
public void GetMonsterAttribute()
{
Console.WriteLine($"编号:{MonsterType},\t生命值:{MonsterAttribute.HealthValue} ,\t伤害值:{MonsterAttribute.ForceValue} ");
}
//实现接口方法,返回一个object对象
public object Clone()
{
//内置的MemberwiseClone()方法,完成对象的拷贝
return this.MemberwiseClone();
}
}

上面修改后的代码将原先的两个字段合并到一个属性类里,产生一个引用类型的字段,修改客户端代码:

=====================修改后的客户端==========================

static void Main(string[] args)
{
Monster monster = new Monster() {
MonsterType = "垃圾小怪",
MonsterAttribute = new MonsterAttribute { HealthValue = 100, ForceValue = 100 }
};

Monster monster1 = (Monster)monster.Clone();
monster1.MonsterType = "普通小怪";
monster1.MonsterAttribute.HealthValue = 200;
monster1.MonsterAttribute.ForceValue = 300;

Monster monster2 = (Monster)monster.Clone();
monster2.MonsterType = "进阶怪物";
monster2.MonsterAttribute.HealthValue = 500;
monster2.MonsterAttribute.ForceValue = 600;

monster.GetMonsterAttribute();
monster1.GetMonsterAttribute();
monster2.GetMonsterAttribute();

Console.ReadLine();
}

=====================结果==========================

包你懂设计模式之:原型模式(Prototype Pattern)

上面的结果可以很好的解释浅复制的弊端,我们从客户端代码来分析下产生上述结果的原因。我们将生命值和伤害值封装到一个新的类中,然后小怪类中加一个字段来存放这个新的类型,这个字段是引用类型,所以我们两次复制后相当于三个小怪的属性都指向了同一个属性对象

包你懂设计模式之:原型模式(Prototype Pattern)

那么做的修改也是针对同一个,这就是上面的结果都是最后一次修改后的数值,都被覆盖了。

深复制就是在浅复制的基础上,再把那些引用类型的成员再复制一份,不再和原型有瓜葛。深复制一般有三种方法:

1、让内部的引用类型也实现ICloneable接口,让他也作为一个原型,在复制外层的时候,它也可以被复制。但是这样的话也会有问题,因为对于复杂的类,它内部可能有多个引用类型,还可能嵌套多层,需要在设计的时候就考虑到,否则很麻烦。

2、给他的内部引用类型重新赋值,则相当于重新开辟一块新的地址。这样就不会和原型指向同一引用,但是同样有弊端,如果内部的很复杂呢?当然很简单的这样是没问题的,比如我们今天这个例子:

包你懂设计模式之:原型模式(Prototype Pattern)

3、先序列化对象,再反序列化,得到新的完整复制品。弊端是要对象能被序列化。

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

包你懂设计模式之:原型模式(Prototype Pattern)

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » 包你懂设计模式之:原型模式(Prototype Pattern)
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏