目錄
- 一、定義
- 二、結(jié)構(gòu)
- 三、優(yōu)點
- 四、使用場景
- 五、代碼示例
- 六、截圖示例
一、定義
- 1.在不改變現(xiàn)有對象結(jié)構(gòu)的情況下,動態(tài)給該對象添加額外功能的模式
- 2.類B繼承于類A,并將類A作為B類的屬性(B類聚合A類)
- 3.BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter都用到了裝飾者模式
二、結(jié)構(gòu)
- 1.抽象構(gòu)件角色(Component):定義一個抽象接口以規(guī)范準(zhǔn)備接收附加責(zé)任的對象
- 2.具體構(gòu)件角色(Concrete Component):實現(xiàn)抽象構(gòu)件,通過裝飾角色為其添加一些職責(zé)
- 3.抽象裝飾角色(Decorator):繼承或?qū)崿F(xiàn)抽象構(gòu)件,并包含具體構(gòu)件的實例,可以通過其子類擴展具體構(gòu)件的功能
- 4.具體裝飾角色(ConcreteDecorator):實現(xiàn)抽象裝飾的相關(guān)方法,并給具體構(gòu)件對象添加附加的責(zé)任
三、優(yōu)點
- 1.裝飾者模式可以帶來比繼承更加靈活性的擴展功能,使用更加方便,可以通過組合不同的裝飾者對象來獲取具有不同行為狀態(tài)的多樣化結(jié)果
- 2.裝飾者模式比繼承更具良好的擴展性,完美的遵循開閉原則,繼承是靜態(tài)的附加責(zé)任,裝飾者則是動態(tài)的附加責(zé)任
- 3.裝飾類和被裝飾類可以獨立發(fā)展,不會互相耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態(tài)擴展一個實現(xiàn)類的功能
四、使用場景
- 1.當(dāng)不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承不利于系統(tǒng)擴展和維護時
- 2.不能采用繼承的情況主要有兩類:1.系統(tǒng)中存在大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長;2.類定義不能被繼承(例如被final修飾的類)
- 3.在不影響其它對象情況下,以動態(tài)、透明的方式給單個對象添加職責(zé)
- 4.當(dāng)對象的功能要求可以動態(tài)添加,也可以動態(tài)撤銷時
五、代碼示例
package com.learning.decorator;import lombok.AllArgsConstructor;
import lombok.Data;/*** 抽象構(gòu)件角色* 快餐類*/
@Data
@AllArgsConstructor
public abstract class FastFood {// 價格private float price;// 名稱private String name;public abstract float cost();public void printFastFood(){System.out.println(this.getName() + " " + this.cost());}
}
package com.learning.decorator;/*** 炒飯類* 具體構(gòu)件角色*/
public class FriedRice extends FastFood{public FriedRice(){super(10, "炒飯");}@Overridepublic float cost() {return getPrice();}
}
package com.learning.decorator;/*** 炒面類* 具體構(gòu)件角色*/
public class FriedNoodles extends FastFood{public FriedNoodles(){super(12, "炒面");}@Overridepublic float cost() {return getPrice();}
}
package com.learning.decorator;import lombok.Getter;
import lombok.Setter;/*** 裝飾者類* 抽象裝飾者角色*/
@Setter
@Getter
public abstract class Garnish extends FastFood{// 聲明快餐類的變量private FastFood fastFood;public Garnish(FastFood fastFood, float price, String name) {super(price, name);this.fastFood = fastFood;}
}
package com.learning.decorator;/*** 雞蛋類* 具體的裝飾者角色*/
public class Egg extends Garnish{public Egg(FastFood fastFood){super(fastFood, 1, "雞蛋");}@Overridepublic float cost() {// 計算價格return getFastFood().cost() + this.getPrice();}@Overridepublic String getName() {return super.getName() + getFastFood().getName();}
}
package com.learning.decorator;/*** 培根類* 具體的裝飾者角色*/
public class Bacon extends Garnish{public Bacon(FastFood fastFood){super(fastFood, 1, "培根");}@Overridepublic float cost() {// 計算價格return getFastFood().cost() + this.getPrice();}@Overridepublic String getName() {return super.getName() + getFastFood().getName();}
}
package com.learning.decorator;public class Client {public static void main(String[] args) {FastFood fastFood = new FriedRice();// 點一份炒飯fastFood.printFastFood();// 炒飯中添加雞蛋fastFood = new Egg(fastFood);fastFood.printFastFood();// 雞蛋炒飯中加培根fastFood = new Bacon(fastFood);fastFood.printFastFood();// 再加一個雞蛋fastFood = new Egg(fastFood);fastFood.printFastFood();}}
六、截圖示例
