java基礎_設計模式_裝飾者模式

本文講闡述自己對裝飾者模式的理解,以及在項目中的應用,書寫的思路圍繞着以下幾個問題一步步開展,希望對大家能有點幫助。

問題思路:
1.什麼是裝飾者模式,官方定義&自己的理解;
2.爲什麼會有這樣的需求(是爲了解決什麼問題),典型的例子;
3.裝飾者模式的優點;
4.裝飾者模式在Android中的應用;
5.剖析在Android中應用的源碼,看看官方的規範並提示自己在使用時要注意的點。


1.什麼是裝飾者模式?

簡單的一句話:動態地給一個對象添加一些額外的職責;我認爲這是對裝飾者模式最好的解釋。

關鍵字:動態地、對象、添加、額外的職責。


2.爲什麼會有這樣的需求,舉兩個典型的例子;

比如:

①假設設計遊戲的時候不同的人形,有的是A對象+白褲子+紅襯衫;B對象+白褲子+白襯衫;A對象+白褲子+白襯衫等等有很多的人形,這個時候你要是每一個對象都寫死屬性,比如這樣:

class A {
    public String getDescription() {
        String description = "白褲子+白襯衫";
        return description;
    }
}
抽象一個父類,然後需要不同屬性的的子類去實現父類,這樣的去實現的話,會有太多的子類,這種現象叫做類爆炸。

通常可以使用繼承來是實現功能的擴展,如果這些需要擴展的功能種類很繁多,那麼必然會生成很多子類,增加系統的複雜性,這種現象叫類爆炸。”

②典型的還有星巴克咖啡點餐管理例子,不同的咖啡+不同的配料,管理計算各種飲料的價格,怎麼去實現。這是典型裝飾者的使用。

具體的代碼是這樣去實現的:

被裝飾者:

/**
 * 咖啡父類
 */

public abstract class Coffee {

    public String description = "";

    /**
     * getCost()方法是抽象的,必須要子類自己去實現
     */
    public abstract double getCost();

    public String getDescription() {
        return description;
    }
}

子類類型:

/**
 * 深培咖啡
 */

public class DarkRoastCoffee extends Coffee {

    public DarkRoastCoffee() {
        description = "深培咖啡";
    }

    @Override
    public double getCost() {
        return 10;
    }


}

/**
 * 濃縮咖啡
 */

public class EspressoCoffee extends Coffee {

    public EspressoCoffee() {
        description = "濃縮咖啡";
    }

    @Override
    public double getCost() {
        return 8.8;
    }
}


裝飾者(配料):

/**
 * 調料父類
 * 繼承Coffee,是爲了擁有公有的超類,這裏的繼承是爲了繼承類型,而不是行爲
 */

public abstract class Condiment extends Coffee {

    @Override
    public abstract String getDescription();

}

這裏的配料繼承的是Coffee,主要是爲了有共同的超類。

在子類去繼承Codiment的時候必然要重寫Condiment中定義的抽象方法和Coffee中定義的抽象方法。

/**
 * 配料牛奶
 */

public class MilkCondiment extends Condiment {
    private final Coffee coffee;

    public double milkPrice = 2.1;

    public MilkCondiment(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public double getCost() {
        return milkPrice + coffee.getCost();
    }

    @Override
    public String getDescription() {
        return coffee.getDescription() + ",加牛奶";
    }
}

/**
 * 摩卡對象是一個裝飾者
 */

public class MochaCondiment extends Condiment {

    private final Coffee coffee;

    public double mochaPrice = 5.2;

    public MochaCondiment(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public double getCost() {
        return mochaPrice+coffee.getCost();
    }

    @Override
    public String getDescription() {
        return coffee.getDescription()+",加摩卡";
    }
}

奶泡:

/**
 * 奶泡配料
 */

public class WhipCondiment extends Condiment {
    private final Coffee coffee;

    private double whipPrice = 3.0;

    public WhipCondiment(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public double getCost() {
        return whipPrice+coffee.getCost();
    }

    @Override
    public String getDescription() {
        return coffee.getDescription()+"加奶泡";
    }
}

使用的時候:

public class Test1Coffee {
    public static void main(String[] args) {
        Coffee mochaCondiment = new MochaCondiment(new MilkCondiment(new DarkRoastCoffee()));
        System.out.println("我曹++"+mochaCondiment.getDescription()+";價格是"+mochaCondiment.getCost());

        Coffee mochaCondiment1 = new MochaCondiment(new MochaCondiment(new DarkRoastCoffee()));
        System.out.println("我曹1++"+mochaCondiment1.getDescription()+";價格是"+mochaCondiment1.getCost());

        Coffee whipCondiment = new WhipCondiment(new MochaCondiment(new EspressoCoffee()));
        System.out.println("我曹2++"+whipCondiment.getDescription()+";價格是"+whipCondiment.getCost());

    }
}
輸出結果:

“我曹++深培咖啡,加牛奶,加摩卡;價格是17.3
我曹1++深培咖啡,加摩卡,加摩卡;價格是20.4
我曹2++濃縮咖啡,加摩卡加奶泡;價格是17.0”

哇塞,多麼有意思的代碼啊。作爲一個非科班出身的程序員,感覺看到這種的代碼有種莫名的興奮啊。

Coffee whipCondiment = new WhipCondiment(new MochaCondiment(new EspressoCoffee()));

 說到這裏解釋這個例子的專用的UML圖如下,大家一看就會明白很多:

圖一:星巴克咖啡點餐管理圖示:


圖二:顧客點了一杯加奶泡加摩卡的深培咖啡圖示:




星巴克咖啡點餐系統基本原理就是這樣。


3.其實在Android中比較典型的應用就是JAVA中IO流:

 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("..")));

這是典型的裝飾者模式。


4.還有一個就是ListView組件addHeaderView()方法的源碼,就比較明顯的使用的是裝飾者模式,具體的源碼分析再接下來會分析。




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