C#實(shí)現(xiàn)裝飾器模式
場(chǎng)景:假設(shè)每次我們?nèi)コ匈徫?,我們都?huì)推一個(gè)購物車,有水果、蔬菜、肉類三種商品,提供給我們選擇,那么這時(shí)候,如果使用裝飾器模式,應(yīng)該如何實(shí)現(xiàn)?
1.什么是裝飾器模式
首先我們知道,如果想要給一個(gè)類或者對(duì)象添加一些行為,可以通過繼承這樣的機(jī)制,通過子類繼承父類的方式,使得子類在擁有自己的行為的時(shí)候,同時(shí)也繼承了父類的一些方法。但是繼承的方式,使得子類和父類之間的耦合增大了,并且這種方法是靜態(tài)的,用戶不能控制增加行為的方式和時(shí)機(jī)。
還有一種方式是使用關(guān)聯(lián)機(jī)制,將一個(gè)類對(duì)象嵌入到另一個(gè)對(duì)象中,由另一個(gè)對(duì)象來決定是否調(diào)用嵌入對(duì)象的行為,以便擴(kuò)展自己的行為,這種嵌入的對(duì)象就成為裝飾器
那么裝飾器模式的動(dòng)機(jī)就是:裝飾模式可以在不需要?jiǎng)?chuàng)造更多子類的情況下,將對(duì)象的功能加以擴(kuò)展。這就是裝飾模式的模式動(dòng)機(jī)。
裝飾器模式的設(shè)計(jì)圖如下:

- Component: 抽象構(gòu)件
- ConcreteComponent: 具體構(gòu)件
- Decorator: 抽象裝飾類
- ConcreteDecorator: 具體裝飾類
2.實(shí)現(xiàn)場(chǎng)景
根據(jù)這個(gè)設(shè)計(jì)圖,我們可以設(shè)計(jì)一下上面場(chǎng)景的實(shí)現(xiàn)
①.原始類-就是那個(gè)購物車(shoppingCart)
②.繼承類A-這里沒有繼承,所以這部分不需要,如果以后需要對(duì)購物車的種類進(jìn)行再細(xì)致的劃分,可以使用
③.裝飾器基類(BaseDecorator)
④.裝入水果、蔬菜、肉類就對(duì)應(yīng)下面的三個(gè)裝飾器A、B、C

實(shí)現(xiàn)代碼:
ShoppingCart.cs
public class ShoppingCart
{
public virtual void Show()
{
}
}BaseDecorator.cs
public class BaseDecorator:ShoppingCart
{
protected ShoppingCart _shoppingCart;
public BaseDecorator(ShoppingCart shoppingCart)
{
_shoppingCart = shoppingCart;
}
public override void Show()
{
if (_shoppingCart != null)
{
base.Show();
}
}
}FruitsDecorator.cs
public class FruitsDecorator:BaseDecorator
{
public FruitsDecorator(ShoppingCart shoppingCart)
: base(shoppingCart)
{
}
public void addFruits()
{
Console.WriteLine("加入了水果。");
}
public override void Show()
{
base.Show();
addFruits();
}
}MeatsDecorator.cs
public class MeatsDecorator : BaseDecorator
{
public MeatsDecorator(ShoppingCart shoppingCart)
: base(shoppingCart)
{
}
public void addMeat()
{
Console.WriteLine("加入了肉。");
}
public override void Show()
{
base.Show();
addMeat();
}
}VegetablesDecorator.cs
public class VegetablesDecorator : BaseDecorator
{
public VegetablesDecorator(ShoppingCart shoppingCart)
: base(shoppingCart)
{
}
public void addVegetable()
{
Console.WriteLine("加入蔬菜。");
}
public override void Show()
{
base.Show();
addVegetable();
}
}Program.cs
ShoppingCart sc = new ShoppingCart(); BaseDecorator bd = new BaseDecorator(sc); //添加水果 FruitsDecorator fd = new FruitsDecorator(bd); fd.Show(); //添加肉 MeatsDecorator md = new MeatsDecorator(fd); md.Show(); //添加蔬菜 VegetablesDecorator vd = new VegetablesDecorator(md); vd.Show();
測(cè)試執(zhí)行:

3.其他應(yīng)用場(chǎng)合
在C#當(dāng)中,應(yīng)用裝飾器的場(chǎng)景是蠻多的,比較典型的是System.IO.Stream

例如使用壓縮流的時(shí)候
//壓縮數(shù)據(jù)
static Byte[] Compress(Byte[] data)
{
//壓縮入這個(gè)內(nèi)存流
using (MemoryStream target = new MemoryStream())
{
using (GZipStream gs = new GZipStream(target,CompressionMode.Compress,true))
{
//把數(shù)據(jù)寫入到壓縮流當(dāng)中
//具體實(shí)現(xiàn)略
}
return target.ToArray();
}
}4.總結(jié)
優(yōu)點(diǎn):
裝飾這模式和繼承的目的都是擴(kuò)展對(duì)象的功能,但裝飾者模式比繼承更靈活
通過使用不同的具體裝飾類以及這些類的排列組合,設(shè)計(jì)師可以創(chuàng)造出很多不同行為的組合
裝飾者模式有很好地可擴(kuò)展性
缺點(diǎn):
裝飾者模式會(huì)導(dǎo)致設(shè)計(jì)中出現(xiàn)許多小對(duì)象,如果過度使用,會(huì)讓程序變的更復(fù)雜。并且更多的對(duì)象會(huì)是的差錯(cuò)變得困難,特別是這些對(duì)象看上去都很像。
使用場(chǎng)景:
需要擴(kuò)展一個(gè)類的功能或給一個(gè)類增加附加責(zé)任。
需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能可以再動(dòng)態(tài)地撤銷。
需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能
到此這篇關(guān)于C#實(shí)現(xiàn)裝飾器模式的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
通過C#調(diào)用cmd來修改服務(wù)啟動(dòng)類型
可以使用System.ServiceProcess.ServiceController這個(gè)類允許連接到正在運(yùn)行或者已停止的服務(wù)、對(duì)其進(jìn)行操作或獲取有關(guān)它的信息但是這個(gè)類并沒有提供修改服務(wù)啟動(dòng)類型的方法,可以通過C#調(diào)用cmd來修改2012-12-12
C#中隱藏TabControl選項(xiàng)卡標(biāo)簽的解決方案
這篇文章主要介紹了C#中隱藏TabControl選項(xiàng)卡標(biāo)簽的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
C# TextBox控件實(shí)現(xiàn)只能輸入數(shù)字的方法
這篇文章主要介紹了C# TextBox控件實(shí)現(xiàn)只能輸入數(shù)字的方法,本文使用TextBox的keypress事件實(shí)現(xiàn)這個(gè)需求,需要的朋友可以參考下2015-06-06
C#調(diào)用WinRar執(zhí)行rar、zip壓縮的方法
這篇文章主要介紹了C#調(diào)用WinRar執(zhí)行rar、zip壓縮的方法,涉及C#針對(duì)winrar的判斷與調(diào)用技巧,需要的朋友可以參考下2015-05-05
C#異步綁定數(shù)據(jù)實(shí)現(xiàn)方法
這篇文章主要介紹了C#異步綁定數(shù)據(jù)實(shí)現(xiàn)方法,實(shí)例分析了C#操作數(shù)據(jù)庫及異步綁定的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
C#實(shí)現(xiàn)Word和ODT文檔相互轉(zhuǎn)換詳解
ODT文檔格式一種開放文檔格式(OpenDocument Text)。本文以C#及VB.NET代碼展示ODT和Word文檔之間相互轉(zhuǎn)換的方法,感興趣的可以學(xué)習(xí)一下2022-05-05
C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法
這篇文章主要介紹了C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10

