網站首頁 編程語言 正文
場景:假設每次我們去超市購物,我們都會推一個購物車,有水果、蔬菜、肉類三種商品,提供給我們選擇,那么這時候,如果使用裝飾器模式,應該如何實現?
1.什么是裝飾器模式
首先我們知道,如果想要給一個類或者對象添加一些行為,可以通過繼承這樣的機制,通過子類繼承父類的方式,使得子類在擁有自己的行為的時候,同時也繼承了父類的一些方法。但是繼承的方式,使得子類和父類之間的耦合增大了,并且這種方法是靜態的,用戶不能控制增加行為的方式和時機。
還有一種方式是使用關聯機制,將一個類對象嵌入到另一個對象中,由另一個對象來決定是否調用嵌入對象的行為,以便擴展自己的行為,這種嵌入的對象就成為裝飾器
那么裝飾器模式的動機就是:裝飾模式可以在不需要創造更多子類的情況下,將對象的功能加以擴展。這就是裝飾模式的模式動機。
裝飾器模式的設計圖如下:
- Component: 抽象構件
- ConcreteComponent: 具體構件
- Decorator: 抽象裝飾類
- ConcreteDecorator: 具體裝飾類
2.實現場景
根據這個設計圖,我們可以設計一下上面場景的實現
①.原始類-就是那個購物車(shoppingCart)
②.繼承類A-這里沒有繼承,所以這部分不需要,如果以后需要對購物車的種類進行再細致的劃分,可以使用
③.裝飾器基類(BaseDecorator)
④.裝入水果、蔬菜、肉類就對應下面的三個裝飾器A、B、C
實現代碼:
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();
測試執行:
3.其他應用場合
在C#當中,應用裝飾器的場景是蠻多的,比較典型的是System.IO.Stream
例如使用壓縮流的時候
//壓縮數據
static Byte[] Compress(Byte[] data)
{
//壓縮入這個內存流
using (MemoryStream target = new MemoryStream())
{
using (GZipStream gs = new GZipStream(target,CompressionMode.Compress,true))
{
//把數據寫入到壓縮流當中
//具體實現略
}
return target.ToArray();
}
}
4.總結
優點:
裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活
通過使用不同的具體裝飾類以及這些類的排列組合,設計師可以創造出很多不同行為的組合
裝飾者模式有很好地可擴展性
缺點:
裝飾者模式會導致設計中出現許多小對象,如果過度使用,會讓程序變的更復雜。并且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。
使用場景:
需要擴展一個類的功能或給一個類增加附加責任。
需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。
需要增加由一些基本功能的排列組合而產生的非常大量的功能
原文鏈接:https://www.cnblogs.com/dcz2015/p/5275692.html
相關推薦
- 2022-08-02 Oracle數據庫丟失表排查思路實戰記錄_oracle
- 2022-05-06 golang導入私有倉庫報錯:“server response: not found:xxx: in
- 2023-10-25 更簡單的方法實現el-calendar日歷組件中點擊上個月、今天、下個月按鈕時的點擊事件
- 2022-07-29 Python控制線程和函數超時處理_python
- 2023-03-25 Pandas庫中iloc[]函數的使用方法_python
- 2022-07-15 Python?并行加速技巧分享_python
- 2022-09-01 C++中的Z字形變換問題_C 語言
- 2023-04-27 react中關于函數調用()與bind?this的原因及分析_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支