闡述
利用繼承設計子類的行爲,是在編譯時靜態決定的,且所有的子類都會繼承到這個行爲。如果用組合的做法擴展對象的行爲,就可以在運行時動態的進行擴展。
裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
OO原則:對擴展開放,對修改關閉。
原理
- Component是被裝飾對象的爸爸,是個接口,定義被裝飾者的行爲
- Decorator是裝飾者的爸爸,它繼承了Component,保證了裝飾者和被裝飾者的類型一致
- Decorator的兒子們都持有一個Component對象的引用,用以對Compoment行爲做“裝飾”
實現
public interface Component {
String DESCRIPTION = "我是component";
default String getDescription(){
return DESCRIPTION;
}
/**
* 裝飾着擴展的行爲
*/
String link();
}
public interface Decorator extends Component {
/**
* 裝飾者覆蓋這個方法添加自己的屬性定義,或者說是擴展這個方法
* @return
*/
@Override
String getDescription();
}
public class ConcreteComponentB implements Component {
@Override
public String link() {
return "我是Component的二兒子對link的實現-->";
}
}
public class ConcreteDecoratorB implements Decorator {
private Component component;
public ConcreteDecoratorB(Component component) {
this.component = component;
}
@Override
public String getDescription() {
return component.getDescription() + "-->我是包裝者B的描述";
}
@Override
public String link() {
return "Decorator的二女兒對Component的link做了裝飾-->" + component.link();
}
}
測試類
public class TestDrive {
public static void main(String[] args) {
Component componentB = new ConcreteComponentB();
componentB = new ConcreteDecoratorA(componentB);
componentB = new ConcreteDecoratorB(componentB);
System.out.println("componentB.getDescription() = " + componentB.getDescription());
System.out.println("componentB.link() = " + componentB.link());
}
}
輸出
componentB.getDescription() = 我是component-->我是包裝者A的描述-->我是包裝者B的描述
componentB.link() = Decorator的二女兒對Component的link做了裝飾-->
Decorator的大女兒對Component的link做了裝飾-->我是Component的二兒子對link的實現-->
總結
- 裝飾者模式用了一個名詞叫“組合”,其實其靈魂是“多態”,看清楚,不是“變態” :)
- 其實用法的思路很簡單,搞一個“裝飾者”接口繼承“被裝飾者”並且@Override想要“裝飾”的方法【不是所有方法,要不然你這不是裝飾是拆遷】,然後不同的裝飾者實現類去對這個方法做裝修。裝修的前提是持有一個被裝飾者的引用,只有這樣,才能對被裝飾者中已經實現的方法“動手動腳”【人都在你屋子裏了,你還不是想幹嘛就幹嘛:)】
Q&A
Q:這麼多Component和Decorator的實現類,豈不是生活“類爆炸”?
A:搞搞“工廠模式”嘛
PS : 西八,又是枯燥的一天 (¯﹃¯)