|
一模式定義
裝飾者模式,是在不改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)擴(kuò)展一個(gè)對(duì)象功能,它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裝真實(shí)的對(duì)象。
- 裝飾對(duì)象和真實(shí)對(duì)象有相同接口,這樣客戶端對(duì)象就可以和真實(shí)對(duì)象相同方式和裝飾對(duì)象交互。
- 裝飾對(duì)象包含一個(gè)真實(shí)對(duì)象的引用。
二模式舉例
1模式分析
我們借用黑心商販制做染色饅頭案例說(shuō)明這一模式。
 2裝飾者模式靜態(tài)類圖
 3代碼示例
3.1創(chuàng)建饅頭接口——IBread
- package com.demo.abs;
-
- /**
- * 饅頭加工接口
- *
- * @author
- *
- */
- public interface IBread {
- // 準(zhǔn)備材料
- public void prepair();
-
- // 和面
- public void kneadFlour();
-
- // 蒸饅頭
- public void steamed();
-
- /**
- * 加工饅頭方法
- */
- public void process();
- }
3.2正常饅頭實(shí)現(xiàn)——NormalBread
- package com.demo.abs;
-
- /**
- * 正常饅頭的實(shí)現(xiàn)
- *
- * @author
- *
- */
- public class NormalBread implements IBread {
- // 準(zhǔn)備材料
- public void prepair() {
- System.out.println("準(zhǔn)備面粉、水以及發(fā)酵粉...");
- }
-
- // 和面
- public void kneadFlour() {
- System.out.println("和面...");
- }
-
- // 蒸饅頭
- public void steamed() {
- System.out.println("蒸饅頭...香噴噴的饅頭出爐了!");
- }
-
- /**
- * 加工饅頭方法
- */
- public void process() {
- // 準(zhǔn)備材料
- prepair();
- // 和面
- kneadFlour();
- // 蒸饅頭
- steamed();
- }
-
- }
3.3創(chuàng)建抽象裝飾者——AbstractBread
- package com.demo.decorator;
-
- import com.demo.abs.IBread;
-
- /**
- * 抽象裝飾者
- *
- * @author
- *
- */
- public abstract class AbstractBread implements IBread {
- // 存儲(chǔ)傳入的IBread對(duì)象
- private final IBread bread;
-
- public AbstractBread(IBread bread) {
- this.bread = bread;
- }
-
- // 準(zhǔn)備材料
- public void prepair() {
- this.bread.prepair();
- }
-
- // 和面
- public void kneadFlour() {
- this.bread.kneadFlour();
- }
-
- // 蒸饅頭
- public void steamed() {
- this.bread.steamed();
- }
-
- // 加工饅頭方法
- public void process() {
- prepair();
- kneadFlour();
- steamed();
-
- }
- }
3.4創(chuàng)建染色劑裝飾者——CornDecorator
- package com.demo.decorator;
-
- import com.demo.abs.IBread;
-
- /**
- * 染色的玉米饅頭
- *
- * @author
- *
- */
- public class CornDecorator extends AbstractBread {
-
- // 構(gòu)造方法
- public CornDecorator(IBread bread) {
- super(bread);
- }
-
- // 黑心商販 開(kāi)始染色了
- public void paint() {
- System.out.println("添加檸檬黃的著色劑...");
- }
-
- // 重載父類的和面方法
- @Override
- public void kneadFlour() {
- // 在面粉中加入 染色劑 之后才開(kāi)始和面
- this.paint();
- // 和面
- super.kneadFlour();
- }
- }
3.5創(chuàng)建甜蜜素裝飾者——SweetDecorator
- package com.demo.decorator;
-
- import com.demo.abs.IBread;
-
- /**
- * 甜蜜素饅頭
- *
- * @author
- *
- */
- public class SweetDecorator extends AbstractBread {
- // 構(gòu)造方法
- public SweetDecorator(IBread bread) {
- super(bread);
- }
-
- // 黑心商販 開(kāi)始添加甜蜜素
- public void paint() {
- System.out.println("添加甜蜜素...");
- }
-
- // 重載父類的和面方法
- @Override
- public void kneadFlour() {
- // 在面粉中加入 甜蜜素 之后才開(kāi)始和面
- this.paint();
- // 和面
- super.kneadFlour();
- }
- }
3.6生產(chǎn)甜玉米饅頭——Client
- package com.demo;
-
- import com.demo.abs.IBread;
- import com.demo.abs.NormalBread;
- import com.demo.decorator.CornDecorator;
- import com.demo.decorator.SweetDecorator;
-
- /**
- * 客戶端應(yīng)用程序
- *
- * @author
- *
- */
- public class Client {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- // 生產(chǎn)裝飾饅頭
- System.out.println("\n====開(kāi)始裝飾饅頭?。?!");
- // 創(chuàng)建普通的正常饅頭實(shí)例
- // 這是我們需要包裝(裝飾)的對(duì)象實(shí)例
- IBread normalBread = new NormalBread();
-
- // 下面就開(kāi)始 對(duì)正常饅頭進(jìn)行裝飾了?。。?nbsp;
- // 使用甜蜜素裝飾饅頭
- normalBread = new SweetDecorator(normalBread);
- // 使用檸檬黃的著色劑裝飾饅頭
- normalBread = new CornDecorator(normalBread);
- // 生產(chǎn)饅頭信息
- normalBread.process();
- System.out.println("====裝飾饅頭結(jié)束?。。?);
-
- }
-
- }
4運(yùn)行結(jié)果
====開(kāi)始裝飾饅頭?。?!
準(zhǔn)備面粉、水以及發(fā)酵粉...
添加檸檬黃的著色劑...
添加甜蜜素...
和面...
蒸饅頭...香噴噴的饅頭出爐了!
====裝飾饅頭結(jié)束!?。?/span>
三該模式設(shè)計(jì)原則
1 封閉變化部分
2 “開(kāi)一閉"原則
3 面向抽象編程
4 優(yōu)先使用組合,而非繼承
四使用場(chǎng)合
1當(dāng)我們需要為某個(gè)現(xiàn)有對(duì)象動(dòng)態(tài)增加一個(gè)新功能或職責(zé)時(shí),可以考慮使用裝飾者模式。
2當(dāng)某個(gè)對(duì)象的職責(zé)經(jīng)常發(fā)生變化或經(jīng)常需要?jiǎng)討B(tài)增加職責(zé),避免為了適應(yīng)這樣的變化而增加繼承子類擴(kuò)展的方式,因?yàn)檫@種方式會(huì)造成子類膨脹速度過(guò)快,難以控制,此時(shí)可以使用裝飾者模式。
五裝飾者模式靜態(tài)類圖

|