本系列文章将向大家介绍一下C#的设计模式,此为第十三篇文章,相信对大家会有所帮助的。废话不多说,继续来看。
意图
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
场景
在设计网络游戏的武器系统时,开始并没有考虑到武器的强化和磨损。之后,策划人员说希望给游戏增加强化系统和修理系统,那么我们的武器类型就需要对外提供强化、磨损、修理等方法了。发生这种改动是我们最不愿意看到的,按照设计原则,我们希望功能的扩展尽可能不要修改原来的程序。你可能会想到使用继承来实现,但是策划人员的需求是有的武器能磨损能修理,不能强化,有的武器能强化,但是不会磨损,有的武器既能强化还能磨损和修理。遇到这样的情况,继承的方案可能不适合了,一来继承的层次可能会很多,二来子类的数量可能会很多。
由此,引入装饰模式来解决这个问题。装饰模式使得我们能灵活赋予类额外的职责,并且使得设计和继承相比更合理。
  示例代码 
  using System; 
  using System.Collections.Generic; 
  using System.Text; 
  namespace DecoratorExample 
  { 
  class Program 
  { 
  static void Main(string[] args) 
  { 
  Weapon w = new Rifle(); 
  w.ShowInfo(); 
  Enhance enhancedWeapon = new Enhance(w); 
  enhancedWeapon.EnhanceAmmo(); 
  enhancedWeapon.ShowInfo(); 
  Wear wornWeapon = new Wear(w); 
  wornWeapon.WearByRate(0.8); 
  wornWeapon.ShowInfo(); 
  } 
  } 
  abstract class Weapon 
  { 
  private double ammo; 
  public double Ammo 
  { 
  get { return ammo; } 
  set { ammo = value; } 
  } 
  private double attack; 
  public double Attack 
  { 
  get { return attack; } 
  set { attack = value; } 
  } 
  private double speed; 
  public double Speed 
  { 
  get { return speed; } 
  set { speed = value; } 
  } 
  private string name; 
  public string Name 
  { 
  get { return name; } 
  set { name = value; } 
  } 
  public abstract void ShowInfo(); 
  } 
  class Rifle : Weapon 
  { 
  public Rifle() 
  { 
  this.Ammo = 100; 
  this.Attack = 10; 
  this.Speed = 5; 
  this.Name = "Rifle"; 
  } 
  public override void ShowInfo() 
  { 
  Console.WriteLine(string.Format("ammo\t{0}", Ammo)); 
  Console.WriteLine(string.Format("attack\t{0}", Attack)); 
  Console.WriteLine(string.Format("speed\t{0}", Speed)); 
  Console.WriteLine(string.Format("name\t{0}", Name)); 
  } 
  } 
  abstract class Decorator : Weapon 
  { 
  protected Weapon w; 
  public Decorator(Weapon w) 
  { 
  this.w = w; 
  } 
  public override void ShowInfo() 
  { 
  w.ShowInfo(); 
  } 
  } 
  class Enhance : Decorator 
  { 
  public Enhance(Weapon w) : base(w) { } 
  public void EnhanceAmmo() 
  { 
  w.Ammo += 20; 
  Console.WriteLine(">>>>>>>>>>>>Enhanced"); 
  } 
  } 
  class Wear : Decorator 
  { 
  public Wear(Weapon w) : base(w) { } 
  public void WearByRate(double rate) 
  { 
  w.Speed = w.Speed * rate; 
  w.Attack = w.Attack * rate; 
  Console.WriteLine(">>>>>>>>>>>>Worn"); 
  } 
  } 
  }