摘要:裝飾者模式裝飾者模式動態地將責任附加到對象上。思維模式首先需要明確一點裝飾者模式利用了組合的思想,避免了繼承的濫用。裝飾者模式的實現我們可以先為每一個零部件確定成本,然后根據需要,動態地組裝組合一個機器人。
裝飾者模式
裝飾者模式動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。思維模式
首先需要明確一點:裝飾者模式利用了“組合”的思想,避免了“繼承”的濫用。
通過動態地組合對象,可以寫新的代碼添加新功能,而無需修改現有代碼。
這就好比拼裝一個機器人。
我們有各種各樣的零部件:
軀干
類人的胳膊
帶有鉗子的胳膊
類人的腿
帶輪子的腿
帶履帶的腿
……
簡單粗暴的實現想要設計各式各樣的機器人,當然我們可以選擇,設計一個Robot超類,然后讓子類繼承這個超類。
這樣,我們可以得到:
軀干+人的胳膊+履帶腿
軀干+鉗子胳膊+輪子腿
軀干+4個人的胳膊+履帶腿
……
根據排列組合的原理,如果我們需要,Robot的子類可以有無限多個。
假如我們從Robot父類處繼承了一個cost()方法,這個方法根據該子類的component(組件)個數和數量來計算成本(cost),那么我們的cost()方法可以說要重寫無數次——因為每一個子類的情況都是不一樣的。
我們可以先為每一個零部件(component)確定成本,然后根據需要,動態地組裝(組合)一個機器人。然后將所有的成本加起來。如此一來,不僅可以得到一個符合我們需求的機器人對象,更能很方便地計算cost。
軀干 $100
類人的胳膊 $40
帶有鉗子的胳膊 $50
類人的腿 $70
帶輪子的腿 $70
帶履帶的腿 $50
……
組合一個有軀干+類人的胳膊+帶履帶的腿的機器人的cost也就是:
100 + 40 + 50 = $190;
所謂組合,也就是我中有你。
如圖所示:
通過保有各個對象的引用,即可實現“組合”。
對于這樣一個組合來的Robot對象,我們不妨稱其為:“robotTom”。
想要求得總成本,可以直接調用robotTom.cost();
這是怎樣實現的呢?
如圖所示:
用公式來表示就是:
[robotTom].cost() = [arm + body].cost() + leg.cost() = [body].cost() + arm.cost() + leg.cost() = body.cost() + arm.cost() + leg.cost();
這里用“leg對象包住arm對象”來形容leg對象中有arm對象的引用,不過對于一個機器人而言,“leg能包住arm”好像有點魔幻現實的味道。
再舉一例我們不妨再舉一個更容易理解的例子:
我們知道,各類繪圖軟件中都有圖層(layer)的概念。
每一個圖層都相當于一層透明紙,我們可以在上面任意地畫東西,而不會影響其他圖層。
把畫著東西的圖層一層一層地疊放(相當于“包裝”)起來,我們就可以得到各式各樣的畫作。
此時,位于上一層的圖層就相當于裝飾者,而所謂的背景圖層就相當于被裝飾者。
其中,
Layer、LayerDecorator為抽象類
LayerDecorator本質上也是Layer
description是各個layer對象的自我描述
position()表示layer對象在某個地方畫一個圖形
RedBackgroundLayer、BlueBackgroundLayer相當于被裝飾者
對應的代碼:
Layer.java:
public abstract class Layer { String description = "我是抽象layer父類"; public String getDescription() { return description; } public abstract String position(); }
RedBackgroundLayer.java
public class RedBackgroundLayer extends Layer { public RedBackgroundLayer (){ //從抽象父類layer繼承來的description description = "我是RedBackgroundLayer->" ; } @Override public String position() { return "我在底層畫一個紅色的layer->"; } }
BlueBackgroundLayer.java
public class BlueBackgroundLayer extends Layer { public BlueBackgroundLayer() { description = "我是一個BlueBackgroundLayer"; } @Override public String position() { return null; } }
各個裝飾者:
RectangleLayerDecorator.java
public class RectangleLayerDecorator extends LayerDecorator { Layer layer; //constructor public RectangleLayerDecorator(Layer layer) {//這一步很重要 this.layer = layer; } @Override public String getDescription() { return layer.getDescription() + "RectangleLayerDecorator->"; } @Override public String position() { return layer.position() + "左上角畫□->"; } }
TriangleLayerDecorator.java
public class TriangleLayerDecorator extends LayerDecorator{ Layer layer; //constructor public TriangleLayerDecorator(Layer layer) { this.layer = layer; } @Override public String getDescription() { return layer.getDescription() + "TriangleLayerDecorator->"; } @Override public String position() { return layer.position() + "右上角畫△->"; } }
RoundLayerDecorator.java
public class RoundLayerDecorator extends LayerDecorator { Layer layer; //constructor public RoundLayerDecorator(Layer layer) { this.layer = layer; } @Override public String getDescription() { return layer.getDescription() + "RoundLayerDecorator->"; } @Override public String position() { return layer.position() + "右下角畫○->"; } }運行Demo
RunDemoTest.java
public class RunDemoTest { public static void main (String[] args ){ //Step 1 Layer backgroundLayer = new RedBackgroundLayer(); System.out.println(backgroundLayer.getDescription() + backgroundLayer.position()); //Step 2 //為RedBackgroundLayer裝飾一個TriangleLayerDecorator Layer multipleLayer = new TriangleLayerDecorator(backgroundLayer); //Step 3 //再裝飾一個RectangleLayerDecorator multipleLayer = new RectangleLayerDecorator(multipleLayer); //Step 4 //再裝飾一個RoundLayerDecorator multipleLayer = new RoundLayerDecorator(multipleLayer); System.out.println(multipleLayer.getDescription() + multipleLayer.position()); } }
運行結果:
我是RedBackgroundLayer->我在底層畫一個紅色的layer-> 我是RedBackgroundLayer->TriangleLayerDecorator->RectangleLayerDecorator->RoundLayerDecorator->我在底層畫一個紅色的layer->右上角畫△->左上角畫□->右下角畫○->
運行過程示意圖:
最終得到:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74811.html
摘要:裝飾者模式組成結構抽象構件給出抽象接口或抽象類,以規范準備接收附加功能的對象。裝飾者模式圖解裝飾者模式應用場景需要擴展一個類的功能,或給一個類添加附加職責。裝飾者對象接受所有來自客戶端的請求。參考資料設計模式 一、了解裝飾者模式 1.1 什么是裝飾者模式 裝飾者模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾者來包裹真實的對...
摘要:相關設計模式裝飾者模式和代理模式裝飾者模式關注再一個對象上動態添加方法代理模式關注再對代理對象的控制訪問,可以對客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關于新職責適配器也可以在轉換時增加新的職責,但主要目的不在此。 0x01.定義與類型 定義:裝飾模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的...
摘要:裝飾者模式遵循了開閉原則,對擴展開放,對修改關閉。但是在使用裝飾者模式的同時可能會引入大量小類,而且使用裝飾者模式除了實例化組件外,還要把組件包裝進裝飾者,會使代碼顯得不易理解。 1. 簡介 ??裝飾者模式是一種結構型模式,它可以動態的將責任附加到對象上,在擴展功能方面,它比繼承更有彈性。裝飾者模式遵循了開閉原則,對擴展開放,對修改關閉。??雖然在裝飾者模式中也使用了繼承,但是繼承只是...
摘要:簡介代理模式和裝飾者模式是兩種常見的設計模式。這里通過構造函數的參數將被代理對象傳入到代理中,也可以通過其它方式,如提供一個方法。下面是的代碼輸出首先依然是先創建一個需要被代理的對象,然后把它傳入到的構造函數中。 簡介 代理模式和裝飾者模式是兩種常見的設計模式。代理模式是為其它對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以...
摘要:這是設計模式系列的第二篇,系列文章目錄如下用一句話總結那些殊途同歸的設計模式工廠策略模版方法美顏相機中的設計模式裝飾者模式幾乎所有的設計模式都是通過增加一層抽象來解決問題。 這是設計模式系列的第二篇,系列文章目錄如下: 用一句話總結那些殊途同歸的設計模式:工廠=?策略=?模版方法 美顏相機中的設計模式——裝飾者模式 幾乎所有的設計模式都是通過增加一層抽象來解決問題。 上一篇中提...
摘要:聲明這個系列為閱讀設計模式與開發實踐曾探著一書的讀書筆記裝飾者模式的定義裝飾者模式能夠在不改變對象自身的基礎上,在程序運行期間給對像動態的添加職責。與繼承相比,裝飾者是一種更輕便靈活的做法。裝飾者模式的作用就是為對象動態的加入某些行為。 聲明:這個系列為閱讀《JavaScript設計模式與開發實踐》 ----曾探@著一書的讀書筆記 裝飾者模式的定義: 裝飾者(decorator)模式能...
閱讀 2109·2021-11-23 09:51
閱讀 2847·2021-11-22 15:35
閱讀 2947·2019-08-30 15:53
閱讀 1046·2019-08-30 14:04
閱讀 3284·2019-08-29 12:39
閱讀 1816·2019-08-28 17:57
閱讀 1103·2019-08-26 13:39
閱讀 560·2019-08-26 13:34