動態地給物件增加額外職責。就增加功能而言,Decorator 比產生子類別更靈活。
初版武器系統未考慮強化/磨損。策劃後續需求:強化系統、修理系統。武器需提供強化、磨損、修理方法。修改原類別違反開閉原則。繼承方案:武器類型 × 功能組合 → 類別爆炸(可強化不可磨損、可磨損不可強化、兩者皆可...)。引入 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 // Component
{
private double _ammo, _attack, _speed;
private string _name;
public double Ammo { get { return _ammo; } set { _ammo = value; } }
public double Attack { get { return _attack; } set { _attack = value; } }
public double Speed { get { return _speed; } set { _speed = value; } }
public string Name { get { return _name; } set { _name = value; } }
public abstract void ShowInfo();
}
class Rifle : Weapon // ConcreteComponent
{
public Rifle() { Ammo = 100; Attack = 10; Speed = 5; Name = "Rifle"; }
public override void ShowInfo()
{
Console.WriteLine($"ammo\t{Ammo}");
Console.WriteLine($"attack\t{Attack}");
Console.WriteLine($"speed\t{Speed}");
Console.WriteLine($"name\t{Name}");
}
}
abstract class Decorator : Weapon // Decorator
{
protected Weapon _w;
public Decorator(Weapon w) { _w = w; }
public override void ShowInfo() => _w.ShowInfo();
}
class Enhance : Decorator // ConcreteDecorator
{
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 *= rate;
_w.Attack *= rate;
Console.WriteLine(">>>>>>>>>> Worn");
}
}
}
new Wear(new Enhance(new Rifle()))| 類型 | 特徵 | 適用場景 |
|---|---|---|
| 透明裝飾 | Client 僅依賴 Component 介面 | 裝飾不新增公共介面 |
| 半透明裝飾 | Client 依賴 ConcreteDecorator | 需呼叫裝飾新增方法(本範例) |