天天看點

設計模式——裝飾者模式

1. 情景

設計模式——裝飾者模式

面館開張了,主營2種面:酸菜面、牛肉面;外加2種配料:雞蛋、豆皮

用裝飾者模式來設計這一訂單系統:

滿足要求:可以傳回點的名稱、計算總價格

2. 設計

大體思路:

設計模式——裝飾者模式

這裡要說的是雞蛋、豆皮是裝飾者,為了讓他可以任意的加配料,傳回仍是面條類。

類設計圖:

設計模式——裝飾者模式

3. 實作

面條抽象類

public abstract class Noodle {
    String description = "Unknown Name";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}      

裝飾者抽象類

public abstract class CondimentDecorator extends Noodle {
    @Override
    public abstract String getDescription();
}      

面條具體類--酸菜面

public class SuancaiNoodle extends Noodle{
    SuancaiNoodle() {
        description = "Suancai Noodle";
    }
    @Override
    public double cost() {
        return 10;
    }
}      

面條具體類--牛肉面

public abstract class Noodle {
    String description = "Unknown Name";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}      

配料具體類--雞蛋

public class Egg extends CondimentDecorator{
    private Noodle noodle;
    Egg(Noodle noodle) {
        this.noodle = noodle;
    }
    @Override
    public String getDescription() {
        return noodle.getDescription() + " + Egg";
    }

    @Override
    public double cost() {
        return noodle.cost() + 2;
    }
}      

配料具體類--豆皮

public class SkinOfTofu extends CondimentDecorator{
    private Noodle noodle;

    SkinOfTofu(Noodle noodle) {
        this.noodle = noodle;
    }

    @Override
    public String getDescription() {
        return noodle.getDescription() + " + SkinOfTofu";
    }

    @Override
    public double cost() {
        return noodle.cost() + 1;
    }
}      

4. 測試

public class NoodleTest {
    public static void main(String[] args) {
        Noodle suancai = new SuancaiNoodle();
        Noodle addEgg = new Egg(suancai);
        Noodle addEggSkin = new SkinOfTofu(addEgg);
        System.out.println(addEggSkin.getDescription());
        System.out.println(addEggSkin.cost());

        System.out.println("-----");

        Noodle beef = new BeefNoodle();
        Noodle addEgg2 = new Egg(beef);
        System.out.println(addEgg2.getDescription());
        System.out.println(addEgg2.cost());
    }
}      

結果

Suancai Noodle + Egg + SkinOfTofu
13.0
-----
Beef Noodle + Egg
14.0      

5.java  I/O

設計模式——裝飾者模式

其中InputStream是抽象元件

其下一列如FileInputStream是抽象裝飾者,BufferedInputStream是具體裝飾者

用法舉例

public class ReadFileTest {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("jihite/test.json");
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedInputStream bis2 = new BufferedInputStream(bis);
            byte[] b = new byte[bis2.available()];
            bis2.read(b);

            System.out.println(new String(b));
            bis2.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}      

6. 歸納

定義:

在不必改變原類檔案和使用繼承的情況下,動态地擴充一個對象的功能。它是通過建立一個包裝對象,也就是裝飾來包裹真實的對象。

設計原則:

  • 多組合、少繼承
  • 對擴充開放、對修改關閉

優點:

  • Decorator模式與繼承關系的都是要擴充對象,但是Decorator可以提供比繼承更多的靈活性
  • 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合

缺點:

  • 比繼承更加靈活也同時意味着更加多的複雜性
  • 導緻設計中出現許多小類,如果過度使用,會使程式變得很複雜