裝飾器模式:動態的給一個對象添加一些額外的職責,就增加新功能來說,裝飾模式比生成子類更加靈活。
簡單來說,裝飾器模式就是在不改動原有類的基礎上,爲擴展原有類功能。
下面是裝飾器模式的基本實現:
原有的類:
/**
* 原始的抽象類
*/
public abstract class Component {
/**
* 原有的功能
*/
public abstract void operation();
}
原有功能實現類:
/**
* 原有的實現類
*/
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("我是原有的功能");
}
}
現在要在不改變原有代碼的基礎上擴展原有功能:
裝飾器類:
/**
* 裝飾器類,繼承了Component類,從外類來擴展Component類的功能,對於Component來說,無需知道Decorator的存在
*/
public abstract class Decorator extends Component {
protected Component component;
public void setComponent(Component component) {
this.component = component;
}
/**
* 擴展的功能
*/
@Override
public void operation(){
if (Objects.nonNull(component)){
component.operation();
}
}
}
具體的擴展功能類A,也就是裝飾對象:
/**
* ConcreteComponent 就是具體的裝飾對象,起到給Component添加職責的功能
*/
public class ConcreteComponentA extends Decorator {
@Override
public void operation() {
// 先執行原Component類的功能再執行本類的功能,相當於對原Component類進行了擴展
super.operation();
this.addBehaviorA();
}
/**
* 擴展的功能
*/
public void addBehaviorA(){
System.out.println("我是ConcreteComponent擴展的功能");
}
}
具體的擴展功能類B:
public class ConcreteComponentB extends Decorator {
@Override
public void operation() {
// 先執行原Component類的功能再執行本類的功能,相當於對原Component類進行了擴展
super.operation();
this.addBehaviorB();
}
/**
* 擴展的功能
*/
public void addBehaviorB(){
System.out.println("我是ConcreteComponentB擴展的功能");
}
}
測試類:
public class DecoratorTest {
public static void main(String[] args) {
ConcreteComponent c = new ConcreteComponent();
ConcreteComponentA d1 = new ConcreteComponentA();
ConcreteComponentB d2 = new ConcreteComponentB();
d1.setComponent(c);
d2.setComponent(d1);
d2.operation();
}
}
運行結果:
我是原有的功能
我是ConcreteComponentA擴展的功能
我是ConcreteComponentB擴展的功能
總結:
裝飾器模式就是利用setComponent來對對象進行包裝的,這樣每個裝飾對象的實現就和如何使用這個對象分離開了,每個裝飾對象只關心自己的功能,不需要關心如何被添加到對象鏈中。裝飾模式就是爲已有的功能動態地添加更多功能的一種方式。
什麼時候用?
當系統需要新功能的時候,是向舊類中添加新的代碼,這些新加的代碼通常裝飾了原有類的職責或主要行爲,它們在主類中加入了新的字段,新的方法和新的邏輯,從而增加了主類的複雜度。而這些新加入的東西僅僅是爲了滿足一些只在某種特定情況下才會執行的特殊的行爲需要。而裝飾模式卻提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,因此,當需要執行特殊行爲時,客戶代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝了對象。
裝飾模式的優點總結下來就是,把類中的裝飾功能從類中移除,這樣就可以簡化原有的類。這樣做的更大好處就是有效地把類的核心職責和裝飾功能區分開了。而且可以去除相關類中重複的裝飾邏輯。
裝飾模式的裝飾順序很重要,最理想的情況是保證裝飾類之間彼此獨立,這樣他們就可以以任意的順序進行組合了。