描述
????裝飾模式(Decorator Pattern)又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案。可以在不改變現(xiàn)有對象的結構的情況下,動態(tài)地擴展其功能。
簡介
????這種模式創(chuàng)建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。換言之,客戶端并不會覺得對象在裝飾前和裝飾后有什么不同。裝飾模式可以在不使用創(chuàng)造更多子類的情況下,將對象的功能加以擴展。

裝飾模式類圖
????如果只有一個ConcreteComponent類,那么可以考慮去掉抽象的Component類(接口),把Decorator作為一個ConcreteComponent子類。

只有一個ConcreteComponent類
????如果只有一個ConcreteDecorator類,那么就沒有必要建立一個單獨的Decorator類,而可以把Decorator和ConcreteDecorator的責任合并成一個類。甚至在只有兩個ConcreteDecorator類的情況下,都可以這樣做。

只有一個ConcreteDecorator類
角色
- 抽象構件(Component)角色:給出一個抽象接口,以規(guī)范準備接收附加責任的對象。
- 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。
- 裝飾(Decorator)角色:持有一個構件(Component)對象的實例,并定義一個與抽象構件接口一致的接口。
- 具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任。
優(yōu)缺點
優(yōu)點
- 裝飾模式與繼承關系的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統(tǒng)動態(tài)決定“貼上”一個需要的“裝飾”,或者除掉一個不需要的“裝飾”。繼承關系則不同,繼承關系是靜態(tài)的,它在系統(tǒng)運行前就決定了。
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創(chuàng)造出很多不同行為的組合。
缺點
- 使用裝飾模式會產(chǎn)生比使用繼承關系更多的對象。更多的對象會使得查錯變得困難,特別是這些對象看上去都很相像。
使用場景
- 當需要給一個現(xiàn)有類添加附加職責,而又不能采用生成子類的方法進行擴充時。例如,該類被隱藏或者該類是終極類或者采用繼承方式會產(chǎn)生大量的子類。
- 當需要通過對現(xiàn)有的一組基本功能進行排列組合而產(chǎn)生非常多的功能時,采用繼承關系很難實現(xiàn),而采用裝飾模式卻很好實現(xiàn)。
- 當對象的功能要求可以動態(tài)地添加,也可以再動態(tài)地撤銷時。
示例
/**
* 抽象構件(Component)角色
*/
public interface Shape {
void draw();
}
/**
* 具體構件(ConcreteComponent)角色
*/
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
/**
* 具體構件(ConcreteComponent)角色
*/
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
/**
* 裝飾(Decorator)角色
*/
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
@Override
public void draw() {
decoratedShape.draw();
}
}
/**
* 具體裝飾(ConcreteDecorator)角色
*/
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape) {
System.out.println("Border Color: Red");
}
}
/**
* 具體裝飾(ConcreteDecorator)角色
*/
public class YellowShapeDecorator extends ShapeDecorator {
public YellowShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape) {
System.out.println("Border Color: Yellow");
}
}
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
ShapeDecorator yellowCircle = new YellowShapeDecorator(new Circle());
ShapeDecorator yellowRectangle = new YellowShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
System.out.println("\nCircle of yellow border");
yellowCircle.draw();
System.out.println("\nRectangle of yellow border");
yellowRectangle.draw();
}
}