定義
像現(xiàn)有的一個對象添加新的功能,同時又不改變其結構,它是作為現(xiàn)有的一個類的包裝。
裝飾模式創(chuàng)建了一個裝飾類,包裝了原有的類,而又不改變其內(nèi)部結構,同時增加新的功能。
適用于
般的,我們?yōu)榱藬U展一個類經(jīng)常使用繼承方式實現(xiàn),由于繼承為類引入靜態(tài)特征,并且隨著擴展功能的增多,子類會很膨脹。在不想增加很多子類的情況下擴展類。
好處
將類的核心職責和裝飾功能區(qū)分開,而且去除相關類中重復的裝飾邏輯。用戶可以有選擇地、按順序地使用裝飾功能包裝對象。
例子
接口及具體實現(xiàn)
public interface Subject {
void show();
}
public class ConcreteSubject implements Subject {
@Override
public void show() {
System.out.println("具體執(zhí)行者運行。。。");
}
}
裝飾者
裝飾者抽象類
public abstract class AbstractDecorator implements Subject {
protected Subject subject;
public AbstractDecorator(Subject subject) {
this.subject = subject;
}
@Override
public void show() {
subject.show();
}
}
增強屬性裝飾類A
public class SubjectDecoratorA extends AbstractDecorator {
private String addState = "增強屬性A";
public SubjectDecoratorA(Subject subject) {
super(subject);
}
@Override
public void show() {
super.show();
System.out.println("具體裝飾類A的增強屬性為" + addState);
}
}
增強方法裝飾類B
public class SubjectDecoratorB extends AbstractDecorator {
public SubjectDecoratorB(Subject subject) {
super(subject);
}
@Override
public void show() {
super.show();
addBehavior();
}
private void addBehavior() {
System.out.println("具體裝飾類B的增強方法運行。。");
}
}
測試類
public class DecoratorDesignTest {
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
new SubjectDecoratorA(concreteSubject).show();
new SubjectDecoratorB(concreteSubject).show();
}
}
例子:
咖啡是一種飲品,咖啡種類有拿鐵、摩卡、卡布奇諾等。 咖啡可以加調料,糖、牛奶等,假設加調料收費。
那么如何解決咖啡加調料的問題。 可以每種組合方式都建一個類,但是這種方式解決不了加多個相同調料的問題,比如加兩包糖
使用裝飾模式來解決這個問題。 咖啡的核心抽取出來:拿鐵、摩卡、卡布奇諾;裝飾點:糖、牛奶。
/**
* 飲品
*
*/
public abstract class Drink {
private String description = "";
private BigDecimal price = BigDecimal.ZERO;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public abstract BigDecimal cost();
}
/**
* 咖啡基類
*/
public class Coffee extends Drink {
@Override
public BigDecimal cost() {
//直接返回價格
return super.getPrice();
}
}
/**
* 拿鐵咖啡
*
*/
public class LatteCoffee extends Coffee {
public LatteCoffee() {
super.setDescription("拿鐵咖啡");
super.setPrice(BigDecimal.ZERO);
}
}
/**
* 摩卡咖啡
*
*/
public class MochaCoffee extends Coffee {
public MochaCoffee() {
super.setDescription("摩卡咖啡");
super.setPrice(BigDecimal.ZERO);
}
}
/**
* 卡布奇諾咖啡
*
*/
public class CappuccinoCoffee extends Coffee {
public CappuccinoCoffee() {
super.setDescription("卡布奇諾咖啡");
super.setPrice(BigDecimal.ZERO);
}
}
/**
* 裝飾類基類
*/
public abstract class Decorator extends Drink {
private Drink drink;
private BigDecimal cost;
private String description;
public Decorator(Drink drink, String description, BigDecimal cost) {
this.drink = drink;
this.description = description;
this.cost = cost;
}
@Override
public BigDecimal cost() {
return drink.cost().add(cost);
}
@Override
public String getDescription() {
return drink.getDescription() + "+" + description;
}
}
/**
* 調料-牛奶
*
*/
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink, "牛奶", BigDecimal.ONE);
}
}
/**
* 調料-糖
*/
public class Sugar extends Decorator {
public Sugar(Drink drink) {
super(drink, "糖", BigDecimal.ONE);
}
}
/**
* 測試類
*/
public class DecoratorDesignTest {
public static void main(String[] args) {
//加兩份糖,一份牛奶的摩卡
Drink firstDrink = new Sugar(new Milk(new Milk(new LatteCoffee())));
System.out.println("商品:" + firstDrink.getDescription() + " \n價格:" + firstDrink.cost());
//一份糖,一份牛奶的拿鐵
Drink secondDrink = new Sugar(new Milk(new LatteCoffee()));
System.out.println("商品:" + secondDrink.getDescription() + " \n價格:" + secondDrink.cost());
}
}