日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

装饰者模式(为对象提供加强的接口)

發(fā)布時(shí)間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 装饰者模式(为对象提供加强的接口) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、裝飾者模式

裝飾者模式:允許你通過將對(duì)象放入包含行為的特殊封裝對(duì)象中來為原來的對(duì)象綁定新的行為,相比生成子類更加靈活。是一種在運(yùn)行期動(dòng)態(tài)給某個(gè)對(duì)象的實(shí)例增加功能的方法。如:在IO的Filter模式就使用了裝飾器模式。在Java標(biāo)準(zhǔn)庫中,InputStream是抽象類,FileInputStream、ServletInputStream、Socket.getInputStream()這些InputStream都是最終數(shù)據(jù)源。

二、例子

現(xiàn)在,如果要給不同的最終數(shù)據(jù)源增加緩沖功能、計(jì)算簽名功能、加密解密功能,那么,3個(gè)最終數(shù)據(jù)源、3種功能一共需要9個(gè)子類。如果繼續(xù)增加最終數(shù)據(jù)源,或者增加新功能,子類會(huì)爆炸式增長,這種設(shè)計(jì)方式顯然是不可取的。Decorator模式的目的就是把一個(gè)一個(gè)的附加功能,用Decorator的方式給一層一層地累加到原始數(shù)據(jù)源上,最終,通過組合獲得我們想要的功能。

例如:給FileInputStream增加緩沖和解壓縮功能,用Decorator模式寫出來如下:

// 創(chuàng)建原始的數(shù)據(jù)源: InputStream fis = new FileInputStream("test.gz"); // 增加緩沖功能: InputStream bis = new BufferedInputStream(fis); // 增加解壓縮功能: InputStream gis = new GZIPInputStream(bis);

或者一次性寫成這樣:

InputStream input = new GZIPInputStream( // 第二層裝飾new BufferedInputStream( // 第一層裝飾new FileInputStream("test.gz") // 核心功能));

觀察BufferedInputStream和GZIPInputStream,它們實(shí)際上都是從FilterInputStream繼承的,這個(gè)FilterInputStream就是一個(gè)抽象的Decorator。我們用圖把Decorator模式畫出來如下:


最頂層的Component是接口,對(duì)應(yīng)到IO的就是InputStream這個(gè)抽象類。ComponentA、ComponentB是實(shí)際的子類,對(duì)應(yīng)到IO的就是FileInputStream、ServletInputStream這些數(shù)據(jù)源。Decorator是用于實(shí)現(xiàn)各個(gè)附加功能的抽象裝飾器,對(duì)應(yīng)到IO的就是FilterInputStream。而從Decorator派生的就是一個(gè)一個(gè)的裝飾器,它們每個(gè)都有獨(dú)立的功能,對(duì)應(yīng)到IO的就是BufferedInputStream、GZIPInputStream等。

三、Decorator模式有什么好處

它實(shí)際上把核心功能和附加功能給分開了。核心功能指FileInputStream這些真正讀數(shù)據(jù)的源頭,附加功能指加緩沖、壓縮、解密這些功能。如果我們要新增核心功能,就增加Component的子類,例如ByteInputStream。如果我們要增加附加功能,就增加Decorator的子類,例如CipherInputStream。兩部分都可以獨(dú)立地?cái)U(kuò)展,而具體如何附加功能,由調(diào)用方自由組合,從而極大地增強(qiáng)了靈活性。

如果我們要自己設(shè)計(jì)完整的Decorator模式,應(yīng)該如何設(shè)計(jì)?

我們還是舉個(gè)栗子:假設(shè)我們需要渲染一個(gè)HTML的文本,但是文本還可以附加一些效果,比如加粗、變斜體、加下劃線等。為了實(shí)現(xiàn)動(dòng)態(tài)附加效果,可以采用Decorator模式。

首先,仍然需要定義頂層接口TextNode:

public interface TextNode {// 設(shè)置text:void setText(String text);// 獲取text:String getText(); }

對(duì)于核心節(jié)點(diǎn),例如,它需要從TextNode直接繼承:

public class SpanNode implements TextNode {private String text;public void setText(String text) {this.text = text;}public String getText() {return "<span>" + text + "</span>";} }

緊接著,為了實(shí)現(xiàn)Decorator模式,需要有一個(gè)抽象的Decorator類:

public abstract class NodeDecorator implements TextNode {protected final TextNode target;protected NodeDecorator(TextNode target) {this.target = target;}public void setText(String text) {this.target.setText(text);} }

這個(gè)NodeDecorator類的核心是持有一個(gè)TextNode,即將要把功能附加到的TextNode實(shí)例。接下來就可以寫一個(gè)加粗功能:

public class BoldDecorator extends NodeDecorator {public BoldDecorator(TextNode target) {super(target);}public String getText() {return "<b>" + target.getText() + "</b>";} }

類似的,可以繼續(xù)加ItalicDecorator、UnderlineDecorator等。客戶端可以自由組合這些Decorator:

TextNode n1 = new SpanNode(); TextNode n2 = new BoldDecorator(new UnderlineDecorator(new SpanNode())); TextNode n3 = new ItalicDecorator(new BoldDecorator(new SpanNode())); n1.setText("Hello"); n2.setText("Decorated"); n3.setText("World");System.out.println(n1.getText()); // 輸出<span>Hello</span>System.out.println(n2.getText()); // 輸出<b><u><span>Decorated</span></u></b>System.out.println(n3.getText()); // 輸出<i><b><span>World</span></b></i>

四、裝飾者模式結(jié)構(gòu)

五、裝飾模式適合應(yīng)用場(chǎng)景

  • 如果你希望在無需修改代碼的情況下即可使用對(duì)象, 且希望在運(yùn)行時(shí)為對(duì)象新增額外的行為, 可以使用裝飾模式。

  • 裝飾能將業(yè)務(wù)邏輯組織為層次結(jié)構(gòu), 你可為各層創(chuàng)建一個(gè)裝飾, 在運(yùn)行時(shí)將各種不同邏輯組合成對(duì)象。 由于這些對(duì)象都遵循通用接口,客戶端代碼能以相同的方式使用這些對(duì)象。

  • 如果用繼承來擴(kuò)展對(duì)象行為的方案難以實(shí)現(xiàn)或者根本不可行, 你可以使用該模式。

  • 許多編程語言使用 final最終關(guān)鍵字來限制對(duì)某個(gè)類的進(jìn)一步擴(kuò)展。 復(fù)用最終類已有行為的唯一方法是使用裝飾模式: 用封裝器對(duì)其進(jìn)行封裝。

    • 類比真實(shí)世界

    六、 與其他模式的關(guān)系

  • 適配器模式可以對(duì)已有對(duì)象的接口進(jìn)行修改, 裝飾模式則能在不改變對(duì)象接口的前提下強(qiáng)化對(duì)象功能。 此外, 裝飾還支持遞歸組合, 適配器則無法實(shí)現(xiàn)。

  • 適配器能為被封裝對(duì)象提供不同的接口, 代理模式能為對(duì)象提供相同的接口, 裝飾則能為對(duì)象提供加強(qiáng)的接口。

  • 責(zé)任鏈模式和裝飾模式的類結(jié)構(gòu)非常相似。 兩者都依賴遞歸組合將需要執(zhí)行的操作傳遞給一系列對(duì)象。 但是, 兩者有幾點(diǎn)重要的不同之處。

    • 責(zé)任鏈的管理者可以相互獨(dú)立地執(zhí)行一切操作, 還可以隨時(shí)停止傳遞請(qǐng)求。
    • 另一方面, 各種裝飾可以在遵循基本接口的情況下擴(kuò)展對(duì)象的行為。 此外,裝飾無法中斷請(qǐng)求的傳遞。
  • 組合模式和裝飾的結(jié)構(gòu)圖很相似, 因?yàn)閮烧叨家蕾囘f歸組合來組織無限數(shù)量的對(duì)象。裝飾類似于組合, 但其只有一個(gè)子組件。 此外還有一個(gè)明顯不同: 裝飾為被封裝對(duì)象添加了額外的職責(zé), 組合僅對(duì)其子節(jié)點(diǎn)的結(jié)果進(jìn)行了 “求和”。但是, 模式也可以相互合作: 你可以使用裝飾來擴(kuò)展組合樹中特定對(duì)象的行為。

  • 使用組合和裝飾的設(shè)計(jì)通常可從對(duì)于原型模式的使用中獲益。 你可以通過該模式來復(fù)制復(fù)雜結(jié)構(gòu), 而非從零開始重新構(gòu)造。

  • 裝飾可讓你更改對(duì)象的外表, 策略模式則讓你能夠改變其本質(zhì)。

  • 裝飾和代理有著相似的結(jié)構(gòu), 但是其意圖卻非常不同。 這兩個(gè)模式的構(gòu)建都基于組合原則, 也就是說一個(gè)對(duì)象應(yīng)該將部分工作委派給另一個(gè)對(duì)象。 兩者之間的不同之處在于代理通常自行管理其服務(wù)對(duì)象的生命周期, 而裝飾的生成則總是由客戶端進(jìn)行控制。

  • 參考文章
    參考文章

    總結(jié)

    以上是生活随笔為你收集整理的装饰者模式(为对象提供加强的接口)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。