結合項目實例 回顧傳統設計模式(三)裝飾者模式
2011-10-02 15:09 熬夜的蟲子 閱讀(757) 評論(1) 收藏 舉報說到這個模式的項目實例 蟲子也滿頭疼的 所謂裝飾者模式說白了動態將職責附加到對象上。如果你在項目某個場景中需要功能擴展根據基類衍生出非常多的子類,那么裝飾者模式無疑是很好的。不過其實在實際的項目中,往往大家不直接衍生子類,而是通過組合的方式,根據邏輯講各種擴展疊加來,對外公布的只是一個標簽一個殼而已。
所以這個章節,蟲子就虛構一個實例了。還拿電商來說、點券贈品系統。
背景:
1.所有點券、優惠券、贈品券、積分繼承同一個基類 基類券
2.不用種類的券可以混合搭配
3.積分根據不同的場景可以配置不同的規則
4.升級禮券在上層禮券基礎上添加
一般情況下 大家可以就這樣設計了
/// <summary>
/// 基卡
/// </summary>
public abstract class BaseCard
{
public string decription;
public abstract double cost();
}
/// <summary>
/// 點卡A
/// </summary>
public class cardA : BaseCard
{
public cardA()
{
decription = "cardA";
}
public override double cost()
{
return 50.00;
}
}
/// <summary>
/// 優惠券A
/// </summary>
public class couponsA : BaseCard
{
public couponsA()
{
decription = "couponsA";
}
public override double cost()
{
return 40.00;
}
}
/// <summary>
/// 優惠券B
/// </summary>
public class couponsB : BaseCard
{
public couponsB()
{
decription = "couponsB";
}
public override double cost()
{
return 30.00;
}
}
/// <summary>
/// 國慶禮券
/// </summary>
public class GQCard : BaseCard
{
cardA a = new cardA();
couponsA ca = new couponsA();
public GQCard()
{
decription = "GQCard";
}
public override double cost()
{
return a.cost() + ca.cost();
}
}
/// <summary>
/// 國慶升級A等禮券
/// </summary>
public class GQACard : BaseCard
{
cardA a = new cardA();
couponsA ca = new couponsA();
couponsB cb = new couponsB();
public GQACard()
{
decription = "GQACard";
}
public override double cost()
{
return a.cost() +ca.cost()+ cb.cost();
}
}
/// 基卡
/// </summary>
public abstract class BaseCard
{
public string decription;
public abstract double cost();
}
/// <summary>
/// 點卡A
/// </summary>
public class cardA : BaseCard
{
public cardA()
{
decription = "cardA";
}
public override double cost()
{
return 50.00;
}
}
/// <summary>
/// 優惠券A
/// </summary>
public class couponsA : BaseCard
{
public couponsA()
{
decription = "couponsA";
}
public override double cost()
{
return 40.00;
}
}
/// <summary>
/// 優惠券B
/// </summary>
public class couponsB : BaseCard
{
public couponsB()
{
decription = "couponsB";
}
public override double cost()
{
return 30.00;
}
}
/// <summary>
/// 國慶禮券
/// </summary>
public class GQCard : BaseCard
{
cardA a = new cardA();
couponsA ca = new couponsA();
public GQCard()
{
decription = "GQCard";
}
public override double cost()
{
return a.cost() + ca.cost();
}
}
/// <summary>
/// 國慶升級A等禮券
/// </summary>
public class GQACard : BaseCard
{
cardA a = new cardA();
couponsA ca = new couponsA();
couponsB cb = new couponsB();
public GQACard()
{
decription = "GQACard";
}
public override double cost()
{
return a.cost() +ca.cost()+ cb.cost();
}
}
設計模式的原則是類應該對擴展開放對修改關閉,而上述設計在禮券升級種類越來越多的情況下并且現有的禮券已經頻繁更新的話 對于龐大的禮券系統肯定是不理想的
那么我們換個思路
/// <summary>
/// 基卡
/// </summary>
public abstract class BaseCard
{
public string decription;
public abstract double cost();
}
/// <summary>
/// 點卡A
/// </summary>
public class cardA : baseoupons
{
BaseCard basec;
public cardA(BaseCard basec)
{
this.basec = basec;
decription = "cardA," + basec.decription;
}
public override double cost()
{
return 50.00 + basec.cost();
}
}
/// <summary>
/// 優惠券A
/// </summary>
public class couponsA : baseoupons
{
BaseCard basec;
public couponsA(BaseCard basec)
{
this.basec = basec;
decription = "couponsA," + basec.decription;
}
public override double cost()
{
return 40.00 + basec.cost();
}
}
/// <summary>
/// 優惠券B
/// </summary>
public class couponsB : baseoupons
{
BaseCard basec;
public couponsB(BaseCard basec)
{
this.basec = basec;
decription = "couponsB," + basec.decription;
}
public override double cost()
{
return 30.00 + basec.cost();
}
}
/// <summary>
/// 基類禮券
/// </summary>
public class baseoupons : BaseCard
{
BaseCard basec;
public baseoupons(BaseCard basec)
{
this.basec = basec;
decription = basec.decription;
}
public baseoupons()
{
}
public override double cost()
{
if (basec != null)
{
return basec.cost();
}
else
{
return 0;
}
}
}
/// 基卡
/// </summary>
public abstract class BaseCard
{
public string decription;
public abstract double cost();
}
/// <summary>
/// 點卡A
/// </summary>
public class cardA : baseoupons
{
BaseCard basec;
public cardA(BaseCard basec)
{
this.basec = basec;
decription = "cardA," + basec.decription;
}
public override double cost()
{
return 50.00 + basec.cost();
}
}
/// <summary>
/// 優惠券A
/// </summary>
public class couponsA : baseoupons
{
BaseCard basec;
public couponsA(BaseCard basec)
{
this.basec = basec;
decription = "couponsA," + basec.decription;
}
public override double cost()
{
return 40.00 + basec.cost();
}
}
/// <summary>
/// 優惠券B
/// </summary>
public class couponsB : baseoupons
{
BaseCard basec;
public couponsB(BaseCard basec)
{
this.basec = basec;
decription = "couponsB," + basec.decription;
}
public override double cost()
{
return 30.00 + basec.cost();
}
}
/// <summary>
/// 基類禮券
/// </summary>
public class baseoupons : BaseCard
{
BaseCard basec;
public baseoupons(BaseCard basec)
{
this.basec = basec;
decription = basec.decription;
}
public baseoupons()
{
}
public override double cost()
{
if (basec != null)
{
return basec.cost();
}
else
{
return 0;
}
}
}
讓我們看看裝飾者模式的強大
BaseCard a = new baseoupons();
a = new cardA(a);
a = new couponsA(a);
a = new couponsB(a);
Console.WriteLine("國慶禮券由"+a.decription+"組成");
Console.WriteLine(a.cost().ToString());
BaseCard b = new cardA(a);
Console.WriteLine("國慶升級禮券由" + b.decription + "組成");
Console.WriteLine(b.cost().ToString());
Console.ReadLine();
a = new cardA(a);
a = new couponsA(a);
a = new couponsB(a);
Console.WriteLine("國慶禮券由"+a.decription+"組成");
Console.WriteLine(a.cost().ToString());
BaseCard b = new cardA(a);
Console.WriteLine("國慶升級禮券由" + b.decription + "組成");
Console.WriteLine(b.cost().ToString());
Console.ReadLine();

總結:繼承屬于擴展形式之一,但不見得是達到彈性設計的最佳方式,在我們的設計當中應該允許行為可以被擴展,而無需修改現有的代碼。就如上述的例子裝飾者模式也可以讓我們擴展行為。不過裝飾者模式也有缺點,它會導致設計中出現許多小對象,如果過度使用,會讓程序變得很復雜。
![]() |
原創作品允許轉載,轉載時請務必以超鏈接形式標明文章原始出處以及作者信息。 作者:熬夜的蟲子 點擊查看:博文索引 |

浙公網安備 33010602011771號