真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

什么是裝飾器模式

本篇內(nèi)容主要講解“什么是裝飾器模式”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“什么是裝飾器模式”吧!

創(chuàng)新互聯(lián)公司專注于魚峰網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供魚峰營銷型網(wǎng)站建設(shè),魚峰網(wǎng)站制作、魚峰網(wǎng)頁設(shè)計(jì)、魚峰網(wǎng)站官網(wǎng)定制、微信小程序定制開發(fā)服務(wù),打造魚峰網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供魚峰網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

裝飾器模式概述

裝飾器模式(Decorator Pattern)也叫作包裝器模式(Wrapper  Pattern),指在不改變原有對象的基礎(chǔ)上,動態(tài)地給一個(gè)對象添加一些額外的職責(zé)。就增加功能來說,裝飾器模式相比生成子類更為靈活,屬于結(jié)構(gòu)型設(shè)計(jì)模式。

英文:

Attach additional responsibilities to an object dynamicallykeeping the same  interface.Decorators provide a flexible alternativeto subclassing for extending  functionality.

裝飾器模式提供了比繼承更有彈性的替代方案(擴(kuò)展原有對象的功能)將功能附加到對象上。因此,裝飾器模式的核心是功能擴(kuò)展。使用裝飾器模式可以透明且動態(tài)地?cái)U(kuò)展類的功能。

生活中的案例

一套毛坯房,沒有裝修之前,看起來非常難看,但只要稍微裝修一番,那就漂亮多了,并且能洗澡、睡覺、做飯等,但本質(zhì)還是房子。

一輛汽車,原本就是一輛代步的車,但是瑪麗加大,配置提升,然后就成了豪車,但本質(zhì)還是一輛代步的車。

一個(gè)女生,原本很平凡,長相一般,但是經(jīng)過一番化妝,再穿點(diǎn)好看的衣服,然后就成了很多人心中的女神了。

總之,經(jīng)過點(diǎn)裝飾后,就是不一樣了,功能增強(qiáng)了。

裝飾器模式通用代碼實(shí)現(xiàn)

我們還是用代碼來實(shí)現(xiàn)一把,程序員都喜歡先搞個(gè)demo,然后再慢慢研究。

//抽象組件 public abstract class Component {     public abstract void operation(); } //具體組件 public class ConcreteComponent extends Component {     @Override     public void operation() {         System.out.println("ConcreteComponent operation");     } } //裝飾器抽象 public abstract class Decorator extends Component {      protected Component component;      public Decorator(Component component) {         this.component = component;     }      @Override     public void operation() {         component.operation();     } } //具體裝飾器 public class ConcreteDecorator extends Decorator {     public ConcreteDecorator(Component component) {         super(component);     }      @Override     public void operation() {         System.out.println("開始前搞點(diǎn)事");         super.operation();         System.out.println("結(jié)束后搞點(diǎn)事");     } } //測試 public class Client {     public static void main(String[] args) {         Component component = new ConcreteDecorator(new ConcreteComponent());         component.operation();     } }

運(yùn)行結(jié)果:

開始前搞點(diǎn)事 ConcreteComponent operation 結(jié)束后搞點(diǎn)事

以上便是裝飾器模式的通用代碼實(shí)現(xiàn),下面我們來分析一下。

裝飾器模式UML圖

什么是裝飾器模式

從UML途中可以看出,其中的角色

裝飾器模式中的角色

  • 抽象組件(Component):可以是一個(gè)接口或者抽象類,充當(dāng)被裝飾類的原始對象,規(guī)定了被裝飾對象的行為。

  • 具體組件(ConcreteComponent):實(shí)現(xiàn)/繼承Component的一個(gè)具體對象,即被裝飾對象。

  • 抽象裝飾器(Decorator):通用的裝飾ConcreteComponent的裝飾器,其內(nèi)部必然有一個(gè)屬性指向Component;其實(shí)現(xiàn)一般是一個(gè)抽象類,主要為了讓其子類按照其構(gòu)造形式傳入一個(gè)Component,這是強(qiáng)制的通用行為。如果系統(tǒng)中裝飾邏輯單一,則并不需要實(shí)現(xiàn)許多裝飾器,可以直接省略該類,而直接實(shí)現(xiàn)一個(gè)具體裝飾器即可。

  • 具體裝飾器(ConcreteDecorator):Decorator的具體實(shí)現(xiàn)類,理論上,每個(gè)ConcreteDecorator都擴(kuò)展了Component對象的一種功能。

小結(jié)

裝飾器模式角色分配符合設(shè)計(jì)模式的里氏替換原則、依賴倒置原則,從而使得其具備很強(qiáng)的擴(kuò)展性,最終滿足開閉原則。

裝飾器模式的實(shí)現(xiàn)原理是,讓裝飾器實(shí)現(xiàn)與被裝飾類(例如ConcreteComponent)相同的接口(例如Component),使得裝飾器與被擴(kuò)展類類型一致,并在構(gòu)造函數(shù)中傳入該接口對象,然后在實(shí)現(xiàn)這個(gè)接口的被包裝類對象的現(xiàn)有功能上添加新功能。由于裝飾器與被包裝類屬于同一類型(均為Component),且構(gòu)造函數(shù)的參數(shù)為其實(shí)現(xiàn)接口類(Component),因此裝飾器模式具備嵌套擴(kuò)展功能,這樣就能使用裝飾器模式一層一層地對底層被包裝類進(jìn)行功能擴(kuò)展了。

實(shí)戰(zhàn)

在實(shí)際開發(fā)中,都會存在系統(tǒng)與系統(tǒng)之間的調(diào)用,假如說我們現(xiàn)在有個(gè)支付功能,現(xiàn)在一切都是沒問題的,但是  我們此時(shí)需要對發(fā)起支付前的請求參數(shù)和支付后的相應(yīng)參數(shù)。進(jìn)行統(tǒng)一處理,原功能不變,只是在原功能上做了一點(diǎn)擴(kuò)展(增強(qiáng))。

老功能代碼如下:

/**  * @author 田先生  * @date 2021-06-02  *  * 歡迎關(guān)注公眾號:java后端技術(shù)全棧  */ public interface IOrderPayService {     String payment(Long orderId, BigDecimal amount); } public class OrderPayServiceImpl implements IOrderPayService {      @Override     public String payment(Long orderId, BigDecimal amount) {         //先調(diào)用余額查詢是否足夠         System.out.println("發(fā)起支付,訂單號:" + orderId + ", 支付金額:" + amount.toString());         //調(diào)用支付系統(tǒng)         String result = "訂單id=" + orderId + "支付完成";         System.out.println("支付結(jié)果:" + result);         return result;     } } public class OrderClient {     public static void main(String[] args) {         IOrderPayService orderPayService = new OrderPayServiceImpl();         orderPayService.payment(10001L,new BigDecimal("5000"));     } }

運(yùn)行輸出:

發(fā)起支付,訂單號:10001, 支付金額:5000 支付結(jié)果:訂單id=10001支付完成

新需求,需要把這些請求參數(shù)和相應(yīng)結(jié)果進(jìn)行單獨(dú)搜集處理,此時(shí)為了不影響原有功能,于是我們可以對其進(jìn)行功能增強(qiáng)。

/**  * @author 田先生  * @date 2021-06-02  *  * 歡迎關(guān)注公眾號:java后端技術(shù)全棧  */ public class OrderPayDecorator implements IOrderPayService {      private IOrderPayService orderPayService;      public OrderPayDecorator(IOrderPayService orderPayService) {         this.orderPayService = orderPayService;     }      @Override     public String payment(Long orderId, BigDecimal amount) {         System.out.println("把這個(gè)訂單信息(發(fā)起支付)" + "訂單id=" + orderId + "支付金額=" + amount.toString() + " 【發(fā)送給MQ】");         String result = orderPayService.payment(orderId, amount);         System.out.println("把訂單支付結(jié)果信息" + result + " 【發(fā)送給MQ】");         return result;     } } public class OrderClient {     public static void main(String[] args) {         IOrderPayService orderPayService =new OrderPayDecorator(new OrderPayServiceImpl());         orderPayService.payment(10001L,new BigDecimal("5000"));     } }

運(yùn)行輸出:

把這個(gè)訂單信息(發(fā)起支付)訂單id=10001支付金額=5000 【發(fā)送給MQ】 發(fā)起支付,訂單號:10001, 支付金額:5000 支付結(jié)果:訂單id=10001支付完成 把訂單支付結(jié)果信息訂單id=10001支付完成 【發(fā)送給MQ】

整個(gè)過程,大家有沒有發(fā)現(xiàn),我們并沒動原有的代碼,僅僅只是做了功能增強(qiáng)。

裝飾器模式在新項(xiàng)目中基本上不會用到,通常都是在老項(xiàng)目中使用,因?yàn)橐延械墓δ懿蛔?,只是做了一些功能增?qiáng)。

大神們是怎么用的

裝飾器設(shè)計(jì)模式在JDK源碼、Spring源碼以及Mybatis源碼中都有。

JDK源碼中

裝飾器模式比較經(jīng)典的應(yīng)用就是 JDK 中的 java.io 包下,InputStream、OuputStream、Reader、Writer  及它們的子類。

以 InputStream 為例

  • FileInputStream 是 InputStream 的子類,用來讀取文件字節(jié)流

  • BufferedInputStream 是 InputStream 的子類的子類,可緩存的字節(jié)流

  • DataInputStream 也是 InputStream 的子類的子類,可直接讀取 Java 基本類型的字節(jié)流

UML圖

什么是裝飾器模式

DataInputStream 中構(gòu)造器入?yún)⒈闶亲约旱母割?InputStream)。

什么是裝飾器模式

如果希望提供一個(gè)可以讀取文件 + 可緩存的字節(jié)流,使用繼承方式,就需要派生 FileBufferedInputStream;

如果希望提供一個(gè)可以讀取文件 + 直接讀取基本類型的字節(jié)流,使用繼承方式,就需要派生 FileDataInputStream。

字節(jié)流功能的增強(qiáng)還包括支持管道 pipe、字節(jié)數(shù)組 bytearray、字節(jié)對象 object、字節(jié)流字符流的轉(zhuǎn)換  等維度,如果用繼承方式,那類的層級與種類會多到爆炸。

為了解決問題,這邊就使用了裝飾器模式。

Spring源碼中

在Spring中,我們可以嘗試?yán)斫庖幌耇ransactionAwareCacheDecorator類,這個(gè)類主要用來處理事務(wù)緩存,代碼如下。

public class TransactionAwareCacheDecorator implements Cache {     private final Cache targetCache;     //構(gòu)造方法入?yún)㈩愋蜑樽约旱母割悾ń涌陬愋停?nbsp;    public TransactionAwareCacheDecorator(Cache targetCache) {         Assert.notNull(targetCache, "Target Cache must not be null");         this.targetCache = targetCache;     }      public Cache getTargetCache() {         return this.targetCache;     }     //... }

TransactionAwareCacheDecorator就是對Cache的一個(gè)包裝,因此,這里也是使用了裝飾器模式。

Mybatis源碼中

MyBatis中關(guān)于Cache和CachingExecutor接口的實(shí)現(xiàn)類也使用了裝飾者設(shè)計(jì)模式。Executor是MyBatis執(zhí)行器,是MyBatis  調(diào)度的核心,負(fù)責(zé)SQL語句的生成和查詢緩存的維護(hù);CachingExecutor是一個(gè)Executor的裝飾器,給一個(gè)Executor增加了緩存的功能。此時(shí)可以看做是對Executor類的一個(gè)增強(qiáng),故使用裝飾器模式是合適的。

在CachingExecutor 中

public class CachingExecutor implements Executor {   //持有組件對象   private Executor delegate;   private TransactionalCacheManager tcm = new TransactionalCacheManager();     //構(gòu)造方法,傳入組件對象   public CachingExecutor(Executor delegate) {     this.delegate = delegate;     delegate.setExecutorWrapper(this);   }   @Override   public int update(MappedStatement ms, Object parameterObject) throws SQLException {       //轉(zhuǎn)發(fā)請求給組件對象,可以在轉(zhuǎn)發(fā)前后執(zhí)行一些附加動作     flushCacheIfRequired(ms);     return delegate.update(ms, parameterObject);   }   //...  }

總結(jié)

看完裝飾器模式后,你是否有感覺,裝飾器模式和代理模式非常的相像,下面我們就來做個(gè)對比。

1.裝飾器模式可以理解為一種特殊的代理模式。

2.裝飾器模式強(qiáng)調(diào)自身的功能擴(kuò)展,透明的擴(kuò)展(即用戶想增強(qiáng)什么功能就增強(qiáng)什么功能),可動態(tài)定制的擴(kuò)展。

3.代理模式強(qiáng)調(diào)的是代理過程的控制。

優(yōu)點(diǎn)

  • 裝飾器是繼承的有力補(bǔ)充,比繼承靈活,在不改變原有對象的情況下,動態(tài)地給一個(gè)對象擴(kuò)展功能,即插即用。

  • 通過使用不同裝飾類及這些裝飾類的排列組合,可以實(shí)現(xiàn)不同效果。

  • 裝飾器模式完全遵守開閉原則。

缺點(diǎn)

  • 會出現(xiàn)更多的代碼、更多的類,增加程序的復(fù)雜性。

  • 動態(tài)裝飾在多層裝飾時(shí)會更復(fù)雜。

到此,相信大家對“什么是裝飾器模式”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


分享名稱:什么是裝飾器模式
當(dāng)前網(wǎng)址:http://weahome.cn/article/gjgdgs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部