總章目錄块请,設計模式(一)基本介紹
一 缴罗、定義
裝飾模式:指在不改變現(xiàn)有對象結構的情況下顽聂,若要擴展此功能,裝飾著提供了比繼承更有彈性的替代方式跳纳。
tip:為什么說比繼承更有彈性,若我們修改基類贪嫂,通過繼承實現(xiàn)的所有子類均需實現(xiàn)和修改方法寺庄。
二、結構
裝飾模式主要包含以下角色。
Component:抽象構件類斗塘,定義抽象接口接收附加責任的對象赢织。
ConcreteComponent:具體構件類,實現(xiàn)抽象構件馍盟,通過裝飾角色添加職責于置。
Decorator:抽象裝飾類,繼承抽象構件贞岭,并包含具體構件的實例八毯,可以通過其子類擴展具體構件的功能。
ConcreteDecorator:具體裝飾類瞄桨,實現(xiàn)抽象裝飾的相關方法话速,并給具體構件對象添加附加的責任。
三芯侥、代碼示例
思考下泊交,我們需要對星巴克各種進行描述,并計算其價格柱查,我們怎么更好的去計算價格廓俭,如果使用繼承的話,又怎么去考慮變化唉工。
看到上面的裝飾模式類圖研乒,我們可以看到裝飾者和被裝飾者都有相同的接口,原因是:裝飾者必須能取代被裝飾者酵紫。
因此,無論咖啡中加載什么配料错维,其本體任然是對飲的的咖啡奖地。
五、簡單實現(xiàn)
Component:咖啡(描述赋焕,價格)
public abstract class Coffee {
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public abstract double cost();
}
ConcreteComponent:濃咖啡 50 拿鐵30
public class EspressoCoffee extends Coffee {
public EspressoCoffee() {
setDescription("濃咖啡");
}
@Override
public double cost() {
return 50d;
}
}
public class LatteCoffee extends Coffee {
public LatteCoffee() {
setDescription("拿鐵");
}
@Override
public double cost() {
return 30d;
}
}
Decorator:
public abstract class CoffeeDecorator extends Coffee {
public abstract String getDescription();
}
ConcreteDecorator:
public class Milk extends CoffeeDecorator {
//**注意這里的對象保存之前的狀態(tài)
Coffee coffee;
public Milk(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDescription() {
return "牛奶";
}
@Override
public double cost() {
return 1.2d + coffee.cost();
}
}
public class Mocha extends CoffeeDecorator {
Coffee coffee;
public Mocha(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDescription() {
return "摩卡";
}
@Override
public double cost() {
return 8.5d + coffee.cost();
}
}
最后我們點咖啡参歹,并計算價格了
public class DecoratorTest {
@Test
public void DecoratorTest() {
//拿鐵 + 牛奶 + 牛奶 + 摩卡=30+1.2+1.2+8.5
Coffee latteCoffee = new LatteCoffee();
latteCoffee = new Milk(latteCoffee);
latteCoffee = new Milk(latteCoffee);
latteCoffee = new Mocha(latteCoffee);
System.out.println("拿鐵價格:" + latteCoffee.cost());
Coffee espressoCoffee=new EspressoCoffee();
System.out.println("濃咖啡:" + espressoCoffee.cost());
}
}
打印日志:
拿鐵價格:40.9
濃咖啡:50.0
其實,通過上述示例我們基本就可以李軍裝飾者的范圍和模式了隆判。當然犬庇,若我們還是不能很好的理解的話,可以去瀏覽下Java I/O 侨嘀,其就是通過裝飾者模式實現(xiàn)的臭挽。