設計模式 (design patterns) 有人覺得很難 有人覺得很神秘
其實他是一種 在特定情境下 使用一些別具巧思的物件導向技巧 的方法
往往直接看定義說明 根本難以理解到底在幹嘛
那不如直接回歸原點 一開始就從[情境]來看看怎麼玩
這回要來玩弄的是 裝飾者模式 (Decorator Pattern)
先拜讀神人文
神人文 其實已經說明得很清楚了 小弟我也不必在此 裝很懂
我的心得是:
當有一群 [本質相近]但又個有些[不盡相同]的東西 的時候 適合使用 裝飾者模式
那就來玩一下吧 我們這麼宅 又覺得 不吃早餐才是一件很嘻哈的事
所以神人舉例的早餐 改成我們熟悉的東東
弄個 武器 抽象類 跟 一些武器
//武器 抽象類
public abstract class Weapon
{
public string Name = "砂鍋大的鐵拳";
public virtual string GetName()
{
return Name;
}
public abstract double AttackPower();
}
//劍
public class Sword : Weapon
{
public Sword()
{
base.Name = "劍";
}
public override double AttackPower()
{
return 10;
}
}
//刀
public class Knife : Weapon
{
public Knife()
{
base.Name = "刀";
}
public override double AttackPower()
{
return 5;
}
}
再弄個 強化武器 抽象裝飾者類 跟 一些強化功能
//強化武器 抽象裝飾者類
public abstract class StrengthenDecorator : Weapon
{
public abstract override double AttackPower();
}
//加長
public class Long : StrengthenDecorator
{
private Weapon _weapon;
public Long(Weapon weapon)
{
_weapon = weapon;
}
public override double AttackPower()
{
return _weapon.AttackPower() + 5;
}
public override string GetName()
{
return "加長的" + _weapon.GetName();
}
}
//鋒利
public class Sharp : StrengthenDecorator
{
private Weapon _weapon;
public Sharp(Weapon weapon)
{
_weapon = weapon;
}
public override double AttackPower()
{
return _weapon.AttackPower() + 20;
}
public override string GetName()
{
return "鋒利的" + _weapon.GetName();
}
}
//劇毒
public class Toxic : StrengthenDecorator
{
private Weapon _weapon;
public Toxic(Weapon weapon)
{
_weapon = weapon;
}
public override double AttackPower()
{
return _weapon.AttackPower() + 100;
}
public override string GetName()
{
return "劇毒的" + _weapon.GetName();
}
}
//傳說
public class Legendary : StrengthenDecorator
{
private Weapon _weapon;
public Legendary(Weapon weapon)
{
_weapon = weapon;
}
public override double AttackPower()
{
return _weapon.AttackPower() + 9999;
}
public override string GetName()
{
return "傳說的" + _weapon.GetName();
}
}
最後 拉些 可有可無的 UI 看看效果
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Weapon weapon;
private void Sword_rb_CheckedChanged(object sender, System.EventArgs e)
{
weapon = new Sword();
Log(weapon.GetName(),
weapon.AttackPower());
Knife_rb.Enabled = Sword_rb.Enabled
= false;
}
private void Knife_rb_CheckedChanged(object sender, System.EventArgs e)
{
weapon = new Knife();
Log(weapon.GetName(),
weapon.AttackPower());
Knife_rb.Enabled = Sword_rb.Enabled
= false;
}
private void GetLong_Click(object sender, System.EventArgs e)
{
weapon = new Long(weapon);
Log(weapon.GetName(),
weapon.AttackPower());
}
private void GetSharp_Click(object sender, System.EventArgs e)
{
weapon = new Sharp(weapon);
Log(weapon.GetName(),
weapon.AttackPower());
}
private void GetToxic_Click(object sender, System.EventArgs e)
{
weapon = new Toxic(weapon);
Log(weapon.GetName(),
weapon.AttackPower());
}
private void GetLegendary_Click(object sender, System.EventArgs e)
{
weapon = new Legendary(weapon);
Log(weapon.GetName(),
weapon.AttackPower());
}
private void Log(string name, double attackPower)
{
Log_lb.Text +=
"勇者OO拾取了 [" + name + "]," +
"攻擊力:" + attackPower + "。" +
Environment.NewLine;
}
}
定番截圖
這個舉例比早餐的 case 合理多了!
回覆刪除sorry for one question
回覆刪除If we can do this with only one List < StrengthenDecorator > (use the same type as your example)
and override the Get_*() to something like this
power = 10 <-- base obj
for (all obj)
power += obj <-- each append obj
return power
and we can have the same result, isn't it ?
By using Decorate Pattern, we have to create a lot of Classes, but I really cannot tell what good of using Decorate
BTW, this is a better example indeed!
刪除Yes, you're right. Decorator Pattern creates a lot of Classes, and there are some ways can get an exactly same result like you say.
回覆刪除Here are some timings I think we can use Decorator Pattern
1. A project already used Decorator Pattern, so you have no choices. (lol. I'm joking, but it could be real a situation.)
2. Sometimes, you wouldn't want to do the similar things when you override methods.
In this example, I just append Name and AttackPower.
If you want to deal with many dissimilar features, you might use a lot of "if" or "switch".
When your features are more complex, your code will become dirty.
On the other hand, using Decorator Pattern can encapsulate each feature in each Classe.
You can make sure that you edit this class won't damage other Classes(In theory), and you will have better readability
To be honest, I didn't use Decorator Pattern in any projects because I haven't face such complex features.
This is just for learning design pattern :)
Thank you for answering kindly.
刪除It seems #1 might be more likely to happen.
Let's see if there is any chance to use this =)
這個舉例真的很棒
回覆刪除:)
回覆刪除這例子秒懂
回覆刪除感謝分享666
厲害了
回覆刪除不知道為啥我一看到遊戲例子我就看得很入迷...很認真....
感謝您的例子, 好文讚啦:)
回覆刪除竟然有這種可以看到讓嘴角一直不爭氣地往上翹,又保有高度專業水準的程式設計文.
回覆刪除讚!
神人文的內容也很讓人好奇,可惜神人文連結已經失效:(
http://www.dotblogs.com.tw/pin0513/archive/2010/01/04/12779.aspx
點部落有改版,現在的網址是這一個
刪除https://www.dotblogs.com.tw/pin0513/2010/01/04/12779