1 定義
裝飾模式也成為包裝模式,此設(shè)計(jì)模式屬于結(jié)構(gòu)型模式。
定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),裝飾模式相比生成子類(lèi)更為靈活。
模式結(jié)構(gòu)

角色介紹
- Component:抽象組件
可以是一個(gè)接口或者抽象類(lèi),定義我們最核心的對(duì)象,也就是被裝飾的原始對(duì)象。 - ConcreteComponent:組件的具體實(shí)現(xiàn)
Component類(lèi)的基本實(shí)現(xiàn),也就是要裝飾的具體對(duì)象。 - Decorator:抽象裝飾者
作用是為了裝飾我們的組件對(duì)象,其內(nèi)部必有一個(gè)指向Component對(duì)象的引用。 - ConcreteDecoratorA:抽象裝飾者的具體實(shí)現(xiàn)。
- ConcreteDecoratorB:抽象裝飾者的具體實(shí)現(xiàn)。
通用模式代碼
- 抽象組件,被裝飾的原始對(duì)象
public abstract class Component {
/**
* 抽象的方法,可以有多個(gè)
*/
public abstract void operate();
}
- 組件的具體實(shí)現(xiàn),即被裝飾的具體對(duì)象
public class ConcreteComponent extends Component{
@Override
public void operate() {
// 在這里寫(xiě)你的邏輯
}
}
- 抽象裝飾者,其內(nèi)部一定要有一個(gè)指向組件對(duì)象的引用。
public class Decorator extends Component{
private Component mComponent; // 持有一個(gè)Component對(duì)象的引用
/**
* 構(gòu)造方法
* @param component
*/
public Decorator(Component component){
this.mComponent=component;
}
@Override
public void operate() {
mComponent.operate();
}
}
- 抽象裝飾者的具體實(shí)現(xiàn)
public class ConcreteDecoratorA extends Decorator{
/**
* 構(gòu)造方法
*
* @param component
*/
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operate() {
// 裝飾方法A和B的調(diào)用順序可變
operateA();
super.operate();
operateB();
}
/**
* 自定義的裝飾方法
*/
public void operateA(){
// 裝飾邏輯
}
/**
* 自定義的裝飾方法
*/
public void operateB(){
// 裝飾邏輯
}
}
public class ConcreteDecoratorB extends Decorator{
/**
* 構(gòu)造方法
*
* @param component
*/
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operate() {
// 裝飾方法A和B的調(diào)用順序可變
operateA();
super.operate();
operateB();
}
/**
* 自定義的裝飾方法
*/
public void operateA(){
// 裝飾邏輯
}
/**
* 自定義的裝飾方法
*/
public void operateB(){
// 裝飾邏輯
}
}
- 測(cè)試代碼
// 構(gòu)造被裝飾的對(duì)象
Component component=new ConcreteComponent();
// 根據(jù)組件對(duì)象構(gòu)造裝飾者對(duì)象A并調(diào)用,此時(shí)相當(dāng)于給組件對(duì)象添加裝飾者A的功能方法
Decorator decoratorA=new ConcreteDecoratorA(component);
decoratorA.operate();
// 根據(jù)組件對(duì)象構(gòu)造裝飾者對(duì)象B并調(diào)用,此時(shí)相當(dāng)于給組件對(duì)象添加裝飾者B的功能方法
Decorator decoratorB=new ConcreteDecoratorB(component);
decoratorB.operate();
三 實(shí)例
我們?cè)僖灾谱髂滩铻槔?,?a href="http://www.itdecent.cn/p/3a7eb444b466" target="_blank">橋接模式里,我們實(shí)現(xiàn)了奶茶兩個(gè)維度的變化,大小杯和加不加糖。在裝飾模式下,我們要實(shí)現(xiàn)裝飾一杯奶茶,動(dòng)態(tài)地給奶茶添加一些功能。比如加冰,加藍(lán)莓,加珍珠,計(jì)算價(jià)格等。
- 抽象組件,被裝飾的原始對(duì)象,在我們的實(shí)例是指制作一杯飲料
/*
* 抽象組件,被裝飾的原始對(duì)象
* @author Jackson
* @version 1.0.0
* since 2019 03 13
*/
public abstract class Beverage {
/**
* 抽象方法,制作飲料
*/
public abstract void makeBeverage();
}
- 組件的具體實(shí)現(xiàn),被裝飾的具體對(duì)象,在我們的實(shí)例,制作一杯奶茶
/*
* 組件的具體實(shí)現(xiàn),被裝飾的具體對(duì)象
* @author Jackson
* @version 1.0.0
* since 2019 03 13
*/
public class MilkTea extends Beverage {
@Override
public void makeBeverage() {
// 奶茶的基本邏輯
System.out.println(" 添加奶茶 ");
}
}
- 抽象的裝飾者,其內(nèi)部保持一個(gè)被裝飾類(lèi)的引用
/*
* 抽象的裝飾者
* @author Jackson
* @version 1.0.0
* since 2019 03 13
*/
public abstract class Decorator extends Beverage {
protected Beverage mBeverage; // 其內(nèi)部保持一個(gè)被裝飾類(lèi)的引用
/**
* 構(gòu)造方法
* @param beverage
*/
public Decorator(Beverage beverage){
this.mBeverage=beverage;
}
@Override
public void makeBeverage() {
// 調(diào)用Beverage的makeBeverage()方法)
mBeverage.makeBeverage();
}
}
- 具體裝飾者,加藍(lán)莓,加冰,加藍(lán)莓的奶茶
/*
* 具體裝飾者,加藍(lán)莓
* @author Jackson
* @version 1.0.0
* since 2019 03 13
*/
public class BlueberryDecorator extends Decorator{
/**
* 構(gòu)造方法
*
* @param beverage
*/
public BlueberryDecorator(Beverage beverage) {
super(beverage);
}
@Override
public void makeBeverage() {
// 順序:加冰--加飲料--加藍(lán)莓--收錢(qián),順序按照需求可變
addIce();
super.makeBeverage();
addBlueberry();
price();
}
/**
* 添加冰塊
*/
private void addIce(){
System.out.println(" 添加冰塊 ");
}
/**
* 添加藍(lán)莓
*/
private void addBlueberry(){
System.out.println(" 添加藍(lán)莓 ");
}
/**
* 計(jì)算價(jià)格
*/
private void price(){
System.out.println(" 藍(lán)莓奶茶的價(jià)格是5元 ");
}
}
- 具體裝飾者,加珍珠的奶茶
/*
* 具體裝飾者,珍珠奶茶
* @author Jackson
* @version 1.0.0
* since 2019 03 13
*/
public class PearlDecorator extends Decorator{
/**
* 構(gòu)造方法
*
* @param beverage
*/
public PearlDecorator(Beverage beverage) {
super(beverage);
}
@Override
public void makeBeverage() {
// 順序:收錢(qián)--加珍珠丸子--加飲料,順序按照需求可變
price();
addPearl();
super.makeBeverage();
}
/**
* 添加珍珠丸子
*/
private void addPearl(){
System.out.println(" 添加珍珠丸子 ");
}
/**
* 計(jì)算價(jià)格
*/
private void price(){
System.out.println(" 珍珠奶茶的價(jià)格是6元 ");
}
}
- 測(cè)試代碼
// 首先要現(xiàn)有一杯奶茶
MilkTea milkTea=new MilkTea();
System.out.println("------制作藍(lán)莓奶茶-------");
// 制作藍(lán)莓奶茶
BlueberryDecorator blueberryDecorator=new BlueberryDecorator(milkTea);
blueberryDecorator.makeBeverage();
// 制作珍珠奶茶
System.out.println("------制作珍珠奶茶-------");
PearlDecorator pearlDecorator=new PearlDecorator(milkTea);
pearlDecorator.makeBeverage();

運(yùn)行結(jié)果
四 優(yōu)點(diǎn)
- 比繼承更靈活
裝飾模式比繼承更加靈活,繼承是靜態(tài)的,而且一旦繼承,所有子類(lèi)都有一樣的功能,而裝飾模式把功能分離到每個(gè)裝飾器中,然后通過(guò)組合的方式,組合的方式?jīng)Q定裝飾后對(duì)象的最終功能。 - 更容易復(fù)用功能
裝飾模式把一系列復(fù)雜的功能分散到每個(gè)裝飾器中,一般一個(gè)裝飾器只實(shí)現(xiàn)一個(gè)功能,從而可以更好地復(fù)用裝飾器。
五 使用場(chǎng)景
- 需要擴(kuò)展一個(gè)類(lèi)的功能,或者給一個(gè)類(lèi)增加附加功能時(shí)可以考慮使用裝飾者模式。