裝飾模式
1)裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案2)裝飾模式可以在不創造更多子類的情況下,將對象的功能加以擴展
3)裝飾模式把客戶端的調用委派到被裝飾類。裝飾模式的關鍵在於這種擴展完全是透明的。
4)裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
裝飾模式的角色
1)抽象構件角色
給出一個抽象接口,以規範準備接收附加責任的對象。如:OutputStream接口
2)具體構件角色
定義一個將要接收附加責任的類 如:FileOutputStream節點類
3)裝飾角色
持有一個構件(Component)對象的引用,並定義一個與抽象構件接口一致的接口
如:FilterOutputStream
4)具體裝飾角色
負責給構件對象“貼上”附加的責任。
如:BufferedOutputStream等過濾類
裝飾模式的特點
2)裝飾對象包含一個真實對象的引用(reference)
3)裝飾對象接收所有來自客戶端的請求。它把這些請求轉發給真實的對象。
4)裝飾對象可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。
實例
public interface IWorker {
public void doSomething();
}
public class ColourWorker implements IWorker {
private IWorker worker;//必須持有抽象構建角色
public ColourWorker(IWorker worker){
this.worker = worker;
}
@Override
public void doSomething() {
System.out.println("上色前");
this.worker.doSomething();
System.out.println("上色後");
}
}
public class WriteWorker implements IWorker {
private IWorker worker;//必須持有抽象構建角色
public WriteWorker(IWorker worker){
this.worker = worker;
}
@Override
public void doSomething() {
System.out.println("題字前");
this.worker.doSomething();
System.out.println("題字後");
}
}
public class Test {
public static void main(String[] args) {
IWorker iWorker = new WriteWorker(new ColourWorker(new BaseWoker()));
iWorker.doSomething();
// print
// 題字前
// 上色前
// 打卡
// 上色後
// 題字後
}
}
public interface Component {
public void doSomething();
}
具體構建功能(個人理解其實就是一個最底層的修飾)
public class ConcreteComponent implements Component {
@Override
public void doSomething() {
System.out.println("基本功能");
}
}
裝飾角色
public class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
component.doSomething();
}
}
具體裝飾角色A
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能A");
}
}
具體裝飾角色B
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能B");
}
}
客戶端
public class Test {
public static void main(String[] args) {
// 節點流
Component component = new ConcreteComponent();
// 過濾流
Component componentA = new ConcreteDecoratorA(component);
componentA.doSomething();
System.out.println("------------");
// 過濾流
Component componentB = new ConcreteDecoratorB(componentA);
componentB.doSomething();
Component test = new ConcreteDecoratorA(new ConcreteDecoratorB(
new ConcreteComponent()));
test.doSomething();
// 基本功能
// 功能A
// ------------
// 基本功能
// 功能A
// 功能B
// 基本功能
// 功能B
// 功能A
}
}
裝飾VS繼承
–用來擴展特定對象的功能
–不需要子類
–動態
–運行時分配職責
–防止由於子類而導致的複雜和混亂
–更多的靈活性
–對於一個給定的對象,同時可能有不同的裝飾
繼承
–用來擴展一類對象的功能
–需要子類
–靜態
–編譯時分派職責
–導致很多子類產生
–缺乏靈活性