What
裝飾器模式(Decorator Design Pattern),是面向?qū)ο缶幊填I(lǐng)域中,一種動態(tài)地往一個類中添加新的行為的設(shè)計模式。就功能而言,裝飾模式相比生成子類更為靈活,這樣可以給某個對象而不是整個類添加一些功能。裝飾器模式背后設(shè)計思想是“組合大于繼承”。它主要的作用是給原始類添加增強功能。這也是判斷是否該用裝飾器模式的一個重要的依據(jù)。
Why
- 一般的,我們?yōu)榱藬U展一個類經(jīng)常使用繼承方式實現(xiàn),由于繼承為類引入靜態(tài)特征,并且隨著擴展功能的增多,子類會很膨脹。因此,如果在不想增加很多子類的情況下擴展類,我們就可以使用裝飾器模式來實現(xiàn)。
- 裝飾類和被裝飾類可以獨立發(fā)展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態(tài)擴展一個實現(xiàn)類的功能。
How
現(xiàn)在的年輕人大多喜歡喝奶茶,奶茶有很多口味,而且每種口味又可以添加很多配料,比如布丁、紅豆、珍珠等等,會有非常非常多的搭配方式,很難去枚舉所有搭配組合。今天就以去買奶茶的例子來給大家講解裝飾器模式的典型實現(xiàn)。
// 首先,創(chuàng)建奶茶接口:
public interface MilkTea {
void make();
Integer price();
}
// 原味奶茶,價格10元
public class OriginMilkTea implements MilkTea{
@Override
public void make() {
System.out.println("This is an origin milk tea.");
}
@Override
public Integer price() {
return 10;
}
}
// 這個類主要目的是方便后面的子類在實現(xiàn)的時候可以只關(guān)注要增強的方法即可。
public class FilterMilkTea implements MilkTea {
protected MilkTea milkTea;
public FilterMilkTea(MilkTea milkTea) {
this.milkTea = milkTea;
}
@Override
public void make() {
this.milkTea.make();
}
@Override
public Integer price() {
return this.milkTea.price();
}
}
// 另加珍珠,2元
public class MilkTeaWithPearl extends FilterMilkTea {
public MilkTeaWithPearl(MilkTea milkTea) {
super(milkTea);
}
@Override
public void make() {
this.milkTea.make();
System.out.println("Add pearl");
}
@Override
public Integer price() {
return this.milkTea.price() + 2;
}
}
// 另加布丁,3元
public class MilkTeaWithPudding extends FilterMilkTea {
public MilkTeaWithPudding(MilkTea milkTea) {
super(milkTea);
}
@Override
public void make() {
this.milkTea.make();
System.out.println("Add pudding");
}
@Override
public Integer price() {
return this.milkTea.price() + 3;
}
}
// 另外加糖,免費,正是因為有了FilterMilkTea,price方法可以不用重寫
public class MilkTeaWithSugar extends FilterMilkTea {
public MilkTeaWithSugar(MilkTea milkTea) {
super(milkTea);
}
@Override
public void make() {
this.milkTea.make();
System.out.println("Add sugar");
}
}
測試效果如下:
// 我:我要來一杯奶茶,加布丁、珍珠和糖。
// 店員:你好,總共15元。
public class TestMain {
public static void main(String[] args) {
MilkTea milkTea = new OriginMilkTea();
MilkTeaWithPearl milkTeaWithPearl = new MilkTeaWithPearl(milkTea);
MilkTeaWithPudding milkTeaWithPudding = new MilkTeaWithPudding(milkTeaWithPearl);
MilkTeaWithSugar milkTeaWithSugar = new MilkTeaWithSugar(milkTeaWithPudding);
milkTeaWithSugar.make();
System.out.println(String.format("It costs you %d RMB", milkTeaWithSugar.price()));
}
}
輸出結(jié)果為:
This is an origin milk tea.
Add pearl
Add pudding
Add sugar
It costs you 15 RMB
裝飾器的實現(xiàn)方法其實和代理模式很像,不過兩者解決問題的側(cè)重點是完全不同的。代理模式主要增加的是非功能性需求,而裝飾器模式則是增加的功能性需求。
代碼地址
寫在最后
如果你覺得我寫的文章幫到了你,歡迎點贊、評論、分享、贊賞哦,你們的鼓勵是我不斷創(chuàng)作的動力~