All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
六步使用ICallbackEventHandler实现无刷新回调_[Asp.Net教程]
Silverlight,2(beta1)数据操作(2)——使用ASP.NET,Web,Service_[Asp.Net教程]
利用PHP和AJAX创建RSS聚合器_[PHP教程]
教你如何做好SQL Server的数据保护_[SQL Server教程]
HTML语言剖析(一)Html简介_[Html教程]
SQL 外链接操作小结 inner join left join right join_[SQL Server教程]
基于.NET数字处理程序的框架设计_.net资料_编程技术
构成Delphi工程的文件:资源文件(.res)
如何在,SQL,Server,2005,中使用,DBCC,SHRINKFILE,语句收缩事务日志文件_[SQL,Server教程]
深入Atlas系列之服务器端支持(上)_.net资料_编程技术
Reading number is top 10 pictures
再发两张抽象画
Look for from human art net, is good--2
NeedWallpaper9
某某人向找小三的人宣战了
NeedWallpaper7
Sora aoi in China4
The money of more than 100 countries and regions13
美丽的桂林风光2
水晶头骨造型的酒瓶
Hunan province aizhai super-large suspension bridge open to traffic and 4 world first1
Download software ranking
WebService在.NET中的实战应用教学视频 → 第1集
jdk1.6 for windows
打鸟视频
Eclipse 4.2.1 For Win32
Unix video tutorial1
Boxer vs Yellow1
Boxer vs Yellow5
Tram sex maniac 2 (H) rar bag9
WebService在.NET中的实战应用教学视频 → 第5集
Boxer's Top ten classic battle8
aaa published in(发表于) 2013/12/18 8:20:24 Edit(编辑)
无废话C#设计模式之五:Prototype_.net资料_编程技术

无废话C#设计模式之五:Prototype_.net资料_编程技术

无废话C#设计模式之五:Prototype_.net资料_编程技术-你的首页-uuhomepage.com

  本系列文章将向大家介绍一下C#的设计模式,此为第五篇文章,相信对大家会有所帮助的。废话不多说,继续来看。


  意图


  用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。


  场景


  游戏场景中的有很多相似的敌人,它们的技能都一样,但是随着敌人出现的位置不同,这些人的能力不太一样。假设,我们现在需要把三个步兵组成一队,其中还有一个精英步兵,能力特别高。那么,你或许可以创建一个敌人抽象类,然后对于不同能力的步兵创建不同的子类。然后,使用工厂方法等设计模式让调用方依赖敌人抽象类。


  问题来了,如果有无数种能力不同步兵,难道需要创建无数子类吗?还有,步兵模型的初始化工作是非常耗时的,创建这么多步兵对象可能还会浪费很多时间。我们是不是可以通过只创建一个步兵原型,然后复制出多个一摸一样的步兵呢?复制后,只需要调整一下这些对象在地图上出现的位置,或者调整一下它们的能力即可。原型模式就是用来解决这个问题的。


  示例代码


  using System;
  using System.Threading;
  using System.Collections.Generic;
  using System.IO;
  using System.Runtime.Serialization.Formatters.Binary;
  using System.Diagnostics;
  namespace PrototypeExample
  {
  class Program
  {
  static void Main(string[] args)
  {
  Stopwatch sw = new Stopwatch();
  sw.Start();
  Enemy enemyPrototype = new FootMan(5, 4, new Location(100, 200));
  GameScene gs = new GameScene();
  List enemyGroup = gs.CreateEnemyGroup(enemyPrototype);
  foreach (FootMan ft in enemyGroup)
  {
  ft.ShowInfo();
  ft.FootmanAttack();
  }
  Console.WriteLine(sw.ElapsedMilliseconds);
  }
  }
  class GameScene
  {
  public List CreateEnemyGroup(Enemy enemyPrototype)
  {
  List enemyGroup = new List();
  Enemy e1 = enemyPrototype.Clone(true);
  e1.Location.x = enemyPrototype.Location.x - 10;
  Enemy e2 = enemyPrototype.Clone(true);
  e2.Location.x = enemyPrototype.Location.x + 10;
  Enemy elite = enemyPrototype.Clone(true);
  elite.Power = enemyPrototype.Power * 2;
  elite.Speed = enemyPrototype.Speed * 2;
  elite.Location.x = enemyPrototype.Location.x;
  elite.Location.y = enemyPrototype.Location.y + 10;
  enemyGroup.Add(e1);
  enemyGroup.Add(e2);
  enemyGroup.Add(elite);
  return enemyGroup;
  }
  }
  [Serializable]
  class Location
  {
  public int x;
  public int y;
  public Location(int x, int y)
  {
  this.x = x;
  this.y = y;
  }
  }
  [Serializable]
  abstract class Enemy
  {
  protected Location location;
  public Location Location
  {
  get { return location; }
  set { location = value; }
  }
  protected int power;
  public int Power
  {
  get { return power; }
  set { power = value; }
  }
  protected int speed;
  public int Speed
  {
  get { return speed; }
  set { speed = value; }
  }
  public abstract Enemy Clone(bool isDeepCopy);
  public abstract void ShowInfo();
  public Enemy(int power, int speed, Location location)
  {
  Thread.Sleep(1000); // Construct method is assumed to be a high calc work.
  this.power = power;
  this.speed = speed;
  this.location = location;
  }
  }
  [Serializable]
  class FootMan : Enemy
  {
  private string model;
  public FootMan(int power, int speed, Location location)
  : base(power, speed, location)
  {
  model = "footman";
  }
  public override void ShowInfo()
  {
  Console.WriteLine("model:{0} power:{1} speed:{2} location:({3},{4})", model, power, speed, location.x, location.y);
  }
  public override Enemy Clone(bool isDeepCopy)
  {
  FootMan footman;
  if (isDeepCopy)
  {
  MemoryStream memoryStream = new MemoryStream();
  BinaryFormatter formatter = new BinaryFormatter();
  formatter.Serialize(memoryStream, this);
  memoryStream.Position = 0;
  footman = (FootMan)formatter.Deserialize(memoryStream);
  }
  else
  footman = (FootMan)this.MemberwiseClone();
  return footman;
  }
  public void FootmanAttack()
  {
  Console.WriteLine("FootmanAttack");
  }
  }
  }


  代码执行结果如下图:



  代码说明


  Enemy类是抽象原型,它有两个用途,一是定义了原型的一些抽象内容,二是定义了原型模式必须的拷贝方法。在这里,我们看到,每个敌人的属性有位置、攻击力、速度等,并且能通过ShowInfo()方法来获取这个人的信息。


  FootMan类就是具体原型了,它显示了敌人的具体参数以及实现了克隆自身。


  GameScene类就是调用方,在这里我们并没有看到有和具体原因进行依赖,通过复制传入的克隆原型,得到一些新的敌人,在原型的基础上稍微调整一下就变成了一支敌人部队。


  原型模式通过对原型进行克隆来替代无数子类,因此也就减少了调用方和具体类型产生依赖的程序。


  Clone()方法接受一个参数,表示是否是深拷贝。在这里,我们通过序列化反序列化实现深拷贝,深拷贝实现对象的完整复制,包括对象内部的引用类型都会复制一份全新的。在这里,如果3个敌人对象的Location都指向内存同一个地址的话,那么它们就分不开了,因此,在复制的时候需要进行深拷贝,使得它们的Location是独立的。


  在初始化Enemy的时候,我们Sleep()了一下,目的是模拟对象的创建是一个非常耗时的工作,这也体现了原型模式的另一个优势,在生成敌人的时候,我们其实无需再做这些工作了,我们只需要得到它的完整数据,并且进行一些修改就是一个新的敌人。


  运行程序后可以看到,虽然创建了三个敌人,但是只耗费了一个敌人的创建时间,三个敌人都是从原型克隆出来的。由于进行了深拷贝,修改了一个敌人的位置并不会影响其它敌人。


  何时采用


  从代码角度来说, 如果你希望运行时指定具体类(比如是使用Footman作为敌人还是使用其它),或者你希望避免创建对象时的初始化过程(如果这个过程占用的时间和资源都非常多),或者是希望避免使用工厂方法来实现多态的时候,可以考虑原型模式。


  从应用角度来说, 如果你创建的对象是多变化、多等级的产品,或者产品的创建过程非常耗时的时候(比如,有一定的计算量,或者对象创建时需要从网络或数据库中获取一定的数据),或者想把产品的创建独立出去,不想了解产品创建细节的时候可以考虑使用。不得不说,原型模式给了我们多一种创建对象,并且不依赖具体对象的选择。


  实现要点


  .NET中使用Object的MemberwiseClone()方法来实现浅拷贝,通过序列化和反序列化实现深拷贝,后者代价比较大,选择何时的拷贝方式。


  原型模式同样需要抽象类型和具体类型,通过相对稳定的抽象类型来减少或避免客户端的修改可能性。


  在代码中,我们把敌人作为了抽象类型,抽象层次很高。完全可以把步兵作为抽象类型,下面有普通步兵,手榴弹步兵等等,再有一个坦克作为抽象类型,下面还有普通坦克和防导弹坦克。这样GameScene可能就需要从两种抽象类型克隆出许多步兵和坦克。不管怎么样抽象,只要是对象类型由原型实例所指定,新对象通过原型实例做拷贝,那么这就是原型模式。


  注意事项


  注意选择深拷贝和浅拷贝。


  拷贝原型并进行修改意味着原型需要公开更多的数据,对已有系统实现原型模式可能修改的代价比较大。





添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.