1. 程式人生 > >設計模式之裝飾器模式

設計模式之裝飾器模式

介紹

概念:向一個現有的物件新增新的功能,同時又不改變其結構。 舉例:現在有一個圓圈,在不改變它的前提,想要把它變成紅色,那麼通過對圓圈進行裝飾(套一層紅色的皮)就能購實現。

裝飾器模式

實現方式:通過引用和繼承來重新父類方法實現。

這裡寫圖片描述

程式碼實現: Shape.java,幾何圖形介面。

/**
 * 幾何圖形,擁有最基本的方法show,用於向外界描述自己
 */
public interface Shape {
    /**
     * 用於向外界描述自己
     */
    void show();
}

Circle.java,圓形實現了幾何圖形介面。

public class
Circle implements Shape {
@Override public void show() { System.out.println("我是一個圓形"); } }

ShapeDecorator.java,幾何圖形介面卡,是一個抽象類,主要為了方便擴充套件多個介面卡。

public abstract class ShapeDecorator implements Shape {
    private Shape shape;

    public ShapeDecorator(Shape shape) {
        this
.shape = shape; } @Override public void show() { shape.show(); } }

RedShapeDecorator.java,紅色幾何圖形介面卡,給幾何圖形塗上紅色,這樣在幾何圖形在向外界描述自己的時候就能帶上“顏色”了。

/**
 * 紅色形狀裝飾器,繼承了抽象類ShapeDecorator
 * 新增了“紅色”描述
 */
public class RedShapeDecorator extends ShapeDecorator {

    public RedShapeDecorator
(Shape shape) { super(shape); } @Override public void show() { super.show(); color(); } /** * 對外不暴露改方法,對於外部呼叫來說,根本不知道該方法的存在 */ private void color() { System.out.println("紅色"); } }

DecoratorPatternDemo.java,介面卡模式執行類

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Shape circle = new Circle();

        Shape redCircle = new RedShapeDecorator(circle);

        System.out.println("-------------------------------");
        circle.show();
        System.out.println("-------------------------------");
        redCircle.show();
    }
}

輸出如下:

-------------------------------
我是一個圓形
-------------------------------
我是一個圓形
紅色

Process finished with exit code 0

如上所述,沒有對Circle.java做任何改動卻在呼叫show方法時,沒經過裝飾的還是原本普通的描述,而經過紅色裝飾器之後在描述中帶上了顏色。

還可以增加其他的介面卡,裝飾原本的圓圈。 EllipseDecorator.java,用於增加“橢圓”的描述

public class EllipseDecorator extends ShapeDecorator {
    public EllipseDecorator(Shape shape) {
        super(shape);
    }

    @Override
    public void show() {
        super.show();
        ext();
    }

    private void ext() {
        System.out.println("橢圓");
    }
}

於是DecoratorPatternDemo可以改成如下:

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Shape circle = new Circle();

        Shape redCircle = new RedShapeDecorator(circle);
        Shape ellipse = new EllipseDecorator(circle);
        Shape redEllipse = new EllipseDecorator(redCircle);

        System.out.println("-------------------------------");
        circle.show();
        System.out.println("-------------------------------");
        redCircle.show();
        System.out.println("-------------------------------");
        ellipse.show();
        System.out.println("-------------------------------");
        redEllipse.show();
        System.out.println("-------------------------------");
    }
}

輸出如下:

-------------------------------
我是一個圓形
-------------------------------
我是一個圓形
紅色
-------------------------------
我是一個圓形
橢圓
-------------------------------
我是一個圓形
紅色
橢圓
-------------------------------

Process finished with exit code 0

裝飾器模式的優缺點

  • 優點 不入侵現有物件的程式碼;因為是使用介面的方式所以介面卡與被介面卡耦合較小;在執行時確定裝飾成什麼樣子(編譯看左邊執行看右邊)。
  • 缺點 多層裝飾比較複雜。

使用場景

如果使用繼承:還是以幾何圖形舉例,但是現在是一個圓圈和一個矩形,我分別想給它們塗上顏色,就得實現一個紅色圓圈子類、一個紅色矩形子類,需要建立兩個類;而通過裝飾者模式,只需要增加一個顏色裝飾者就可以了。 也就是說,當會產生大量的子類,使得系統變得臃腫時使用裝飾者模式更合理。