設計模式(八)裝飾模式

概念

裝飾模式能夠在不改變原類文件和繼承的情況下,動態的寬展一個對象的功能,通過創建一個包裝對象來包裹真實的對象。

模式結構

在這幾類角色結構中,必須擴展Component的功能,但Component並不知道Docorator的存在,ConcreteDocorator纔是具體的裝飾對象,起了給Component添加職責的作用。

  • 抽象構建角色(Component):抽象接口,用來規範準備接口附加責任的對象;
  • 具體構建角色(ConcreteComponent):定義一個將要接口附加責任的類;
  • 裝飾角色(Docorator):定義一個與抽象構建角色一致的接口,持有一個抽象構建角色的引用;
  • 具體的裝飾角色(ConcreteDocorator):負責給構建角色添加附加責任。

示例說明

/**
 * 抽象構建角色
 */
public interface Icomponent {
    void showCoffee();
    double showPrice();
}

/**
 * 具體的構建角色
 */
class Coffee implements Icomponent{
    private String name;
    private double price;

    public Coffee(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public void showCoffee() {
        System.out.println(this.name+"咖啡");
    }

    @Override
    public double showPrice() {
        return this.price;
    }
    // 省略get,set方法
}

/**
 * 裝飾角色
 */
abstract class Docorator implements Icomponent{
    private Icomponent component;

    public void setComponent(Icomponent component) {
        this.component = component;
    }

    @Override
    public void showCoffee() {
        component.showCoffee();
    }

    @Override
    public double showPrice() {
        return component.showPrice();
    }
}

/**
 * 具體的裝飾角色1
 */
class Milk extends Docorator{
    @Override
    public void showCoffee() {
        System.out.print("加奶的");
        super.showCoffee();
    }

    @Override
    public double showPrice() {
        return 20.0 + super.showPrice();
    }
}

/**
 * 具體的裝飾角色2
 */
class Sugar extends Docorator{
    @Override
    public void showCoffee() {
        System.out.print("加糖的");
        super.showCoffee();
    }

    @Override
    public double showPrice() {
        return 10.0 + super.showPrice();
    }
}

class DocoratorClient{
    public static void main(String[] args){
        Icomponent coffee = new Coffee("藍山", 80.0);
        Docorator milk = new Milk();
        Docorator sugar = new Sugar();

        coffee.showCoffee();
        System.out.println(coffee.showPrice());
        System.out.println("======================================");

        milk.setComponent(coffee);
        milk.showCoffee();
        System.out.println(milk.showPrice());
        System.out.println("======================================");

        sugar.setComponent(milk);
        sugar.showCoffee();
        System.out.println(sugar.showPrice());
    }
}
運行結果:

藍山咖啡
80.0
======================================
加奶的藍山咖啡
100.0
======================================
加糖的加奶的藍山咖啡
110.0

裝飾模式的思考起點就是利用“多用組合,少用繼承”的原則;Java中裝飾模式典型的使用是I/0流;裝飾模式和AOP在思想上有共同之處。

裝飾模式優缺點

  • 比繼承更靈活:繼承是靜態的,一旦繼承,多有子類都有同樣的功能;而裝飾則是把功能分散到每個裝飾器中,然後通過對象組合的方式,動態的組合調用;
  • 更容易複用功能:功能分散到每個裝飾器中,每個裝飾器的功能相對簡單,有利於複用;
  • 簡化高層定義:通過組合個方式給對象增加更多的功能,不需要在定義頂層類的時候把所有的功能都定義出來;
  • 會產生很多細粒度對象:由於功能細分到每個裝飾器,這樣裝飾器類會越來越多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章