重走Java設計模式——裝飾器模式(Decorator Pattern)
裝飾器模式
定義
裝飾器模式(Decorator Pattern)允許向一個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的一個包裝。
這種模式建立了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
程式碼示例
我們將建立一個 Shape
介面和實現了 Shape 介面的實體類。然後我們建立一個實現了 Shape
介面的抽象裝飾類 ShapeDecorator
,並把 Shape
物件作為它的例項變數。
1.建立一個Shape介面
Shape.java
public interface Shape { void draw(); }
2.建立實現介面的實體類
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }
3.建立實現了 Shape 介面的抽象裝飾類
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
4.建立擴充套件了 ShapeDecorator 類的實體裝飾類
RedShapeDecorator.java
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");
}
}
5.使用 RedShapeDecorator 來裝飾 Shape 物件
DecoratorPatternDemo.java
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(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();
}
}
6.驗證輸出
Circle with normal border
Shape: Circle
Circle of red border
Shape: Circle
Border Color: Red
Rectangle of red border
Shape: Rectangle
Border Color: Red
優缺點
優點
1、裝飾者模式可以提供比繼承更多的靈活性
2、可以通過一種動態的方式來擴充套件一個物件的功能,在執行時選擇不同的裝飾器,從而實現不同的行為。
3、通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一物件,得到功能更為強大的物件。
4、具體構件類與具體裝飾類可以獨立變化,使用者可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有程式碼無須改變,符合“開閉原則”。
缺點
1、會產生很多的小物件,增加了系統的複雜性。
2、這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯,排錯也很困難,對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為煩瑣。
使用場景
1、在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。
2、需要動態地給一個物件增加功能,這些功能也可以動態地被撤銷。
3.當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴充套件和維護時。
使用的注意事項
可代替繼承。