描述
????裝飾模式(Decorator Pattern)又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴(kuò)展對象的功能悍引,是繼承關(guān)系的一個替代方案恩脂。可以在不改變現(xiàn)有對象的結(jié)構(gòu)的情況下趣斤,動態(tài)地擴(kuò)展其功能俩块。
簡介
????這種模式創(chuàng)建了一個裝飾類,用來包裝原有的類浓领,并在保持類方法簽名完整性的前提下玉凯,提供了額外的功能。換言之联贩,客戶端并不會覺得對象在裝飾前和裝飾后有什么不同漫仆。裝飾模式可以在不使用創(chuàng)造更多子類的情況下,將對象的功能加以擴(kuò)展泪幌。
????如果只有一個ConcreteComponent類盲厌,那么可以考慮去掉抽象的Component類(接口),把Decorator作為一個ConcreteComponent子類祸泪。
????如果只有一個ConcreteDecorator類吗浩,那么就沒有必要建立一個單獨(dú)的Decorator類,而可以把Decorator和ConcreteDecorator的責(zé)任合并成一個類没隘。甚至在只有兩個ConcreteDecorator類的情況下懂扼,都可以這樣做。
角色
- 抽象構(gòu)件(Component)角色:給出一個抽象接口右蒲,以規(guī)范準(zhǔn)備接收附加責(zé)任的對象微王。
- 具體構(gòu)件(ConcreteComponent)角色:定義一個將要接收附加責(zé)任的類。
- 裝飾(Decorator)角色:持有一個構(gòu)件(Component)對象的實例品嚣,并定義一個與抽象構(gòu)件接口一致的接口炕倘。
- 具體裝飾(ConcreteDecorator)角色:負(fù)責(zé)給構(gòu)件對象“貼上”附加的責(zé)任。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對象的功能翰撑,但是裝飾模式可以提供比繼承更多的靈活性罩旋。裝飾模式允許系統(tǒng)動態(tài)決定“貼上”一個需要的“裝飾”啊央,或者除掉一個不需要的“裝飾”。繼承關(guān)系則不同涨醋,繼承關(guān)系是靜態(tài)的瓜饥,它在系統(tǒng)運(yùn)行前就決定了。
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合浴骂,設(shè)計師可以創(chuàng)造出很多不同行為的組合乓土。
缺點(diǎn)
- 使用裝飾模式會產(chǎn)生比使用繼承關(guān)系更多的對象。更多的對象會使得查錯變得困難溯警,特別是這些對象看上去都很相像趣苏。
使用場景
- 當(dāng)需要給一個現(xiàn)有類添加附加職責(zé),而又不能采用生成子類的方法進(jìn)行擴(kuò)充時梯轻。例如食磕,該類被隱藏或者該類是終極類或者采用繼承方式會產(chǎn)生大量的子類。
- 當(dāng)需要通過對現(xiàn)有的一組基本功能進(jìn)行排列組合而產(chǎn)生非常多的功能時喳挑,采用繼承關(guān)系很難實現(xiàn)彬伦,而采用裝飾模式卻很好實現(xiàn)。
- 當(dāng)對象的功能要求可以動態(tài)地添加伊诵,也可以再動態(tài)地撤銷時单绑。
示例
/**
* 抽象構(gòu)件(Component)角色
*/
public interface Shape {
void draw();
}
/**
* 具體構(gòu)件(ConcreteComponent)角色
*/
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
/**
* 具體構(gòu)件(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();
}
}