本文實例代碼:github.com/JamesZBL/ja…java
裝飾器(Decorator)模式用於動態地給一個對象添加一些額外的職責。 就增長功能來講, Decorator模式相比生成子類更爲靈活。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案。git
純粹的裝飾模式很難找到,大多數的裝飾模式的實現都是「半透明」的,而不是徹底透明的。換言之,容許裝飾模式改變接口,增長新的方法。半透明的裝飾模式是介於裝飾模式和適配器模式之間的。適配器模式的用意是改變所考慮的類的接口,也能夠經過改寫一個或幾個方法,或增長新的方法來加強或改變所考慮的類的功能。 大多數的裝飾模式其實是半透明的裝飾模式,這樣的裝飾模式也稱作半裝飾、半適配器模式。github
如下狀況使用Decorator模式bash
在不影響其餘對象的狀況下, 以動態、 透明的方式給單個對象添加職責。ide
處理那些能夠撤消的職責。this
當不能採用生成子類的方法進行擴充時。 一種狀況是, 可能有大量獨立的擴展, 爲支持每一種組合將產生大量的子類, 使得子類數目呈爆炸性增加。 另外一種狀況多是由於類定義被隱藏, 或類定義不能用於生成子類。spa
Component:定義一個對象接口, 能夠給這些對象動態地添加職責。code
ConcreteComponent:定義一個對象, 能夠給這個對象添加一些職責。cdn
Decorator:持有一個指向 Component 對象的引用,並定義一個與 Component 接口一致的接口。對象
ConcreteDecorator:一貫組件添加職責。
[站外圖片上傳中...(image-a0ad13-1526278884853)]
鐵匠和木匠同時製做一把鐵錘,第一種方案是木匠製做錘把,鐵匠製做錘頭;第二中方案是鐵匠先製做錘把再製做錘頭(假定這裏的木匠只會製做錘把)。製做過程分爲三部分:1.對材料進行初步的檢查,2.進行製造並把部件安裝起來以供後面的操做,3.完成以後再次進行檢查,確保沒有質量問題。
首先定義「操做」接口,包括先後兩次檢查以及安裝的操做。
/** * 流水線上操做行爲的接口 */
public interface Operation {
void checkBefore();
void join();
void chekcAfter();
}
複製代碼
如今只由木匠製做錘把,定義一個木匠的操做類 CarpenterOperation
/** * 木匠的工做 */
public class CarpenterOperation implements Operation {
private static final Logger LOGGER = LoggerFactory.getLogger(CarpenterOperation.class);
@Override
public void checkBefore() {
LOGGER.info("檢查木材");
}
@Override
public void join() {
LOGGER.info("打造錘把");
}
@Override
public void chekcAfter() {
LOGGER.info("檢查成品錘把");
}
}
複製代碼
因爲某些緣由,鐵匠決定本身製做錘把,如今鐵匠身兼雙職,將木匠的工做也承擔了。定義一個鐵匠操做類 HammerSmith
/** * 鐵匠 */
public class HammerSmithOperation implements Operation {
private static final Logger LOGGER = LoggerFactory.getLogger(HammerSmithOperation.class);
private Operation previousOperation;
public HammerSmithOperation(Operation previousOperation) {
this.previousOperation = previousOperation;
}
@Override
public void checkBefore() {
previousOperation.checkBefore();
LOGGER.info("檢查鐵材");
}
@Override
public void join() {
previousOperation.join();
LOGGER.info("打造錘頭");
}
@Override
public void chekcAfter() {
previousOperation.chekcAfter();
LOGGER.info("檢查成品錘頭");
}
}
複製代碼
一樣實現了「操做」的接口,鐵匠的每一個操做都包含了木匠相應的操做,至關於對木匠的操做增長了一層包裹和擴展。這種包裝就是 Decorator 模式中的裝飾。
如今分別讓木匠和鐵匠進行一系列操做
/** * Decorator */
public class Application {
private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
LOGGER.info("僅由木匠製做錘把");
Operation carpenter = new CarpenterOperation();
carpenter.checkBefore();
carpenter.join();
carpenter.chekcAfter();
LOGGER.info("由鐵匠完成錘把以及錘頭的製做");
Operation hammerSmith = new HammerSmithOperation(carpenter);
hammerSmith.checkBefore();
hammerSmith.join();
hammerSmith.chekcAfter();
}
}
複製代碼
輸出以下內容
僅由木匠製做錘把
檢查木材
打造錘把
檢查成品錘把
由鐵匠完成錘把以及錘頭的製做
檢查木材
檢查鐵材
打造錘把
打造錘頭
檢查成品錘把
檢查成品錘頭
複製代碼
1. 裝飾模式和靜態繼承的機制的做用都是對現有的類增長新的功能,但裝飾模式有着比靜態繼承更靈活的組合方式。裝飾模式能夠在運行的時候決定須要增長仍是去除一種「裝飾」以及什麼「裝飾」。靜態繼承則沒有這樣的靈活性,它對類功能的擴展是在運行以前就肯定了的。
2. 得益於裝飾模式在組合上的靈活性和便利性,咱們能夠將各類裝飾類進行組合,從而較爲簡單的創造各類不一樣的行爲集合,實現多種多樣的功能。
1. 裝飾者的對象和它裝飾的對象本質上是徹底不一樣的,裝飾模式會生成許多的對象,致使區分各類對象變得困難
2. 因爲使用相同的標識,對於程序的理解和排錯過程的難度也會隨之增長
我的博客同步更新,獲取更多技術分享請關注:鄭保樂的博客