結(jié)構(gòu)型-裝飾者模式

1、一個實例

在一家咖啡店有很多種咖啡,但都基于一種基本飲料開發(fā)出來的,每一種咖啡也可以加入很多不同的配料。
飲料有:HouseBlend(首選咖啡),Espresso(濃縮咖啡),DarkRoast(焦炒咖啡),Decaf(脫因咖啡)
調(diào)料有:Milk(牛奶)、摩卡(mocha)、豆?jié){(Soy)、奶泡(Whip)
這時候用戶下單要打印票據(jù)顯示配方和價格,該如何做呢?

//被裝飾者父類
public abstract class Beverage {
    String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}
//創(chuàng)建幾個實現(xiàn)類
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "House Blend Coffee";
    }

    @Override
    public double cost() {
        return 0.89;
    }
}
public class DarkRoast extends Beverage {

    public Espresso() {
        description = "DarkRoast";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

  • 裝飾類(寫法1)
//創(chuàng)建裝飾者
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}
// 創(chuàng)建具體的裝飾者
public class Mocha extends CondimentDecorator {
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.2 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Mocha";
    }
}

public class Milk extends CondimentDecorator {
    Beverage beverage;

    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.1 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Milk";
    }
}
  • 裝飾類(寫法2)
//創(chuàng)建裝飾者父類
public abstract class CondimentDecorator extends Beverage {
    protected Beverage beverage;

    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }

    public abstract String getDescription();

}
// 創(chuàng)建具體的裝飾者
public class Mocha extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    @Override
    public double cost() {
        return 0.2 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Mocha";
    }
}

public class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    @Override
    public double cost() {
        return 0.1 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Milk";
    }
}
  • main方法
public class StartbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new DarkRoast();
        //一杯不加調(diào)料的咖啡
        System.out.println(beverage.getDescription() + ",價格:" + beverage.cost());
        //用摩卡和牛奶裝飾下
        Beverage beverage2 = new DarkRoast();
        beverage2=new Mocha(beverage2);
        beverage2=new Milk(beverage2);
        System.out.println(beverage2.getDescription() + ",價格:" + beverage2.cost());

        Beverage beverage3=new Milk(new Mocha(new DarkRoast()));
        System.out.println(beverage3.getDescription() + ",價格:" + beverage3.cost());
    }
}
輸出
DarkRoast,價格:1.99
DarkRoast,Mocha,Milk,價格:2.29
DarkRoast,Mocha,Milk,價格:2.29
1652267688(1).png

2、什么是裝飾者模式

2.1、定義裝飾者模式

動態(tài)地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更具有彈性的替代方案。

2.2 特征

  • 裝飾者和被裝飾者有相同的超類型。
  • 可以用一個或多個裝飾者包裝一個對象。
  • 對象可以在任何時候被裝飾

怎么看出來是使用了裝飾模式呢?
當你看到 new BufferedInputStream(new FileInputStream("test.txt"));這種寫法就差不多了。

  • 裝飾者和被裝飾者有相同的超類型
  • 裝飾者持有超類型的引用,這樣裝飾者就可以不斷的修飾 被裝飾者

3、 java中的實例

1652342401(1).png

上圖是java中的inputStream。我們可以看出來FilterInputStream就是我們的裝飾者。

//被裝飾者父類
public abstract class InputStream{
    public abstract int read() ;
}
//實現(xiàn)類(具體被裝飾者)
public class FileInputStream extends InputStream{
  public FileInputStream(File file){}
  public int read() throws IOException{}
}
public class StringBufferInputStream extends InputStream {
  public synchronized int read(){}
  public StringBufferInputStream(String s) { }
}
public class ByteArrayInputStream extends InputStream {
    public ByteArrayInputStream(byte buf[]) {}
    public synchronized int read(){}
}

  • 裝飾類
//創(chuàng)建裝飾者
public class FilterInputStream extends InputStream {
  protected volatile InputStream in;
  protected FilterInputStream(InputStream in) {
        this.in = in;
    }
  public int read() throws IOException {
        return in.read();
    }
}
// 創(chuàng)建具體的裝飾者
public class BufferedInputStream extends FilterInputStream {
  public synchronized int read(){}
}

  • 具體使用
 public static void main(String[] args){
  InputStream in = new BufferedInputStream(new FileInputStream("test.txt"));
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容