裝飾模式又叫包裝模式。以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案。裝飾模式把客戶端的調用委派到被裝飾類。裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
裝飾模式的角色:
1. 抽象構件角色(Component)
2. 具體構件角色(ConcreteComponent)
3. 裝飾角色(Decorator):持有一個構件(Component)對象的引用,並且定義了與抽象構件接口一樣的接口。
4. 具體裝飾角色(ConcreteDecorator):負責加上額外的功能。
類圖:
源碼實現:
抽象構件角色(Component)
package com.decorate;
public interface Component {
void doSomething();
}
具體構件角色(ConcreteComponent)
package com.decorate;
public class ConcreteComponent implements Component {
@Override
public void doSomething() {
System.out.println("Concrete Component.");
}
}
裝飾角色(Decorator)
package com.decorate;
public class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
component.doSomething();
System.out.println("Decorator.");
}
}
具體裝飾角色(ConcreteDecorator)
package com.decorate;
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething();
doAnthorThing();
}
private void doAnthorThing() {
System.out.println("Concrete Decorator A.");
}
}
package com.decorate;
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething();
doAnthorThing();
}
private void doAnthorThing() {
System.out.println("Concrete Decorator B.");
}
}
客戶端:
package com.decorate;
public class Client {
public static void main(String[] args) {
Component a0 = new ConcreteComponent();
Component a1 = new ConcreteDecoratorA(a0);// 包裝類
Component b1 = new ConcreteDecoratorB(a1);// 包裝類
b1.doSomething();
System.out.println("-------等價於下面--------");
Component component = new ConcreteDecoratorB(new ConcreteDecoratorA(
new ConcreteComponent()));
component.doSomething();
}
}
裝飾模式在文件流中用的最多。
裝飾模式的特點:
1.裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以以和真實對象相同的方式和裝飾對象交互。
2.裝飾對象包含一個真實對象的引用(reference)。
3. 裝飾對象接收所有來自客戶端的請求。它把這些請求轉發給真實的對象。
4.裝飾對象可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。