裝飾器模式又叫包裝模式,資料結構型模式;是指在不改變現有物件結構的情況下,動態的給改物件增加一些職責(即增加其額外功能)的模式。
在星巴克咖啡店,有美式咖啡(longblack)、無因咖啡(decaf)、義大利農咖啡(espresso)等不同的咖啡種類,也可以新增牛奶(milk)、豆漿(soy)、巧克力(chocolate)等調料。下面我們就以這個為例子講解裝飾器模式。
使用傳統的方式設計,就是每一種咖啡和每一種調料都寫乙個類,都繼承自drink抽象類。這樣的缺點是每增加乙個單品咖啡,或者增加乙個新的調料,類的數量就會成倍增加,形成類**。
裝飾器模式的uml類圖:
從上圖可以看到裝飾器模式主要有抽象構件角色、具體構件角色、抽象裝飾角色、具體裝飾角色等四個角色:
使用裝飾器模式完成上面例子的uml類圖:
抽象構件角色:
package com.charon.decorator;
/** * @classname: drink
* @description:
* @author: charon
* @create: 2022-03-19 22:48
*/public abstract class drink
/*** sets the desc
** @param desc desc
*/public void setdesc(string desc)
/*** gets the value of price
** @return the value of price
*/public float getprice()
/*** sets the price
** @param price price
*/public void setprice(float price)
/*** 計算費用的方法,交給子類實現
* @return
*/public abstract float cost();
}
具體構建角色:
package com.charon.decorator;
/** * @classname: coffee
* @description:
* @author: charon
* @create: 2022-03-19 22:37
*/public class coffee extends drink
}package com.charon.decorator;
/** * @classname: longblack
* @description:
* @author: charon
* @create: 2022-03-19 23:16
*/public class longblack extends coffee
}package com.charon.decorator;
/** * @classname: decaf
* @description:
* @author: charon
* @create: 2022-03-19 23:11
*/public class decaf extends coffee
}
抽象裝飾角色:
package com.charon.decorator;
/** * @classname: decorator
* @description:
* @author: charon
* @create: 2022-03-19 23:13
*/public class decorator extends drink
@override
public float cost()
@override
public string getdesc()
}
具體裝飾角色:
package com.charon.decorator;
/** * @classname: milk
* @description:
* @author: charon
* @create: 2022-03-19 23:17
*/public class milk extends decorator
}package com.charon.decorator;
/** * @classname: soy
* @description:
* @author: charon
* @create: 2022-03-19 23:18
*/public class soy extends decorator
}
測試:
package com.charon.decorator;
/** * @classname: client
* @description:
* @author: charon
* @create: 2022-03-19 23:19
*/public class client
}列印:
美式咖啡 費用: 5.0
新增了: 牛奶 && 美式咖啡 費用:7.0
新增了: 豆漿 && 牛奶 && 美式咖啡 費用:8.5
裝飾器模式以對客戶端透明的方式擴充套件物件的功能,是繼承關係的乙個替代方案。
裝飾器模式的優點:
裝飾器模式是對繼承的有利補充,比繼承靈活,在不改變原有物件的情況下,動態的給乙個物件擴充套件功能,即插即用
通過使用不同裝飾類及這些裝飾類的排列組合,可以實現不同的效果
裝飾器模式完全遵循「開閉原則」
裝飾器模式的缺點:
下面介紹其適用的應用場景,裝飾器模式通常在以下幾種情況使用。
第一次看裝飾器模式,總感覺用橋接模式也能實現出來。但是其實兩者還是有區別的。
裝飾器模式的辦法就是把每個子類中比基類多出來的行為放到單獨的類裡面。這樣當這些描述額外行為的物件被封裝到基類物件裡面時,就得到了所需要的子類物件,將這些描述額外行為的類,排列組合可以造出很多的功能組合來,如果用靜態繼承的辦法建立這些組合出來的類所涉及到工作量很大,以致實際上很難做到。裝飾器模式要求所有的這些「額外行為類」具有相同的介面。
橋接模式的解決辦法則又有所不同,橋接模式把原來的兩個基類的實現化細節抽出來,再建造乙個實現化的等級結構中,然後再把原有的基類改造成乙個抽象化等級結構。橋接模式中抽象化角色的子類不能像裝飾器模式那樣巢狀,橋接模式卻可以連續使用。換言之,乙個橋接模式的實現化角色可以成為下一步橋接模式的抽象化角色。
而裝飾器模式不是要改變被裝飾物件的介面,而是恰恰要保持原有的介面,但是增強原有物件的功能,或者改變原有物件的處理方式而提公升效能。所以這兩個模式設計的目的是不同的。
在jdk中,inputstreamreader是乙個介面卡,因為它把inputstream的api轉換成reader的api。inputstream是被適配的類,而 reader是適配的目標類。inputstreamreader做為介面卡類把inputstream類的乙個例項包裝起來,從而能夠把inputstream的api。
而bufferreader是乙個裝飾器類,因為它實現reader,並且包裝了乙個reader。類似地,bufferedinputstream、outputstream、writer 各自都是它們自己的裝飾類。linenumberreader、filterreader和 pushbackreader均是reader的裝飾類,因為它們自己是reader類,而且包裝其他的reader類。chararrayreader、filereader、pipedreader和stringreader類不是裝飾類,因為它們包裝的是字元數值組、file、pipedwriter和string類。它們應該被看做字元數值組、file、pipedwriter 和string類的介面卡類。
設計模式之裝飾器模式
定義 decorator裝飾器,顧名思義,就是動態地給乙個物件新增一些額外的職責,就好比為房子進行裝修一樣。因此,裝飾器模式具有如下的特徵 它必須具有乙個裝飾的物件。它必須擁有與被裝飾物件相同的介面。它可以給被裝飾物件新增額外的功能。用一句話總結就是 保持介面,增強效能。裝飾器通過包裝乙個裝飾物件來...
設計模式之裝飾器模式
什麼是裝飾器模式 decorator 裝飾器模式的優點 裝飾器模式的缺點 示例 package com.pattern.decorator 抽象類,裝飾器的父類 author yjzhou public abstract class decorator implements component ov...
設計模式之裝飾器模式
裝飾模式 decorator 顧名思義,裝飾模式就是給乙個物件增加一些新的功能,而且是動態的,要求裝飾物件和被裝飾物件實現同乙個介面,裝飾物件持有被裝飾物件的例項,關係圖如下 source類是被裝飾類,decorator類是乙個裝飾類,可以為source類動態的新增一些功能,如下 1.public ...