意圖
動態地給一個對象添加一些額外的職責。就增加功能來說,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");
}
}
}