為什麼不通過修改介面或者選擇書寫繼承介面的新子類,偏偏選擇新增上一個裝飾器?
1.盆友們,其實這個問題挺簡單的,還記得單純我們為啥選擇定義介面呀抽象類呀(這些框架、模板的)嗎?
大白話--“方便批量生產”+ “不破壞原有類結構”。(最後會放上介面和繼承重寫的作用的哈)
記住“方便批量生產” + 不破化基礎上再擴充套件,現在回過頭來思考新增裝飾器的作用就很簡單啦。
在實際的應用開發中,我們知道,實現了一開始定義好的介面的子類已經有好多個了,但是現在我們有了新的需求是想要擁有好多個在原來子類的繼承上功能得到擴充套件的新子類。於是乎,為了批量生產這批新增了新功能的子類,我們選擇了裝飾器,做到了在不破壞原有的類的結構基礎上進行擴充套件。同時還避免了兩個尷尬:
(1)如果選擇修改原來介面導致的麻煩是,原來那批實現介面的子類都需要需改了;
(2)如果選擇在實現原來介面的基礎上,每個實現類新增上新功能,太多子類啦!!!
2.所以我們選擇了裝飾器(封裝原有的類,通過依賴關係實現擴充套件功能)。
首先我們定義了一個抽象類的裝飾器實現原來介面,然後定義一個介面物件屬性,(為了封裝原有的類),通過定義帶參構造方法,把介面物件作為引數。裝飾器的好處是做到了不破壞原有的類的結構的基礎進行了擴充套件。
為啥要定義成抽象類的裝飾器呢,複習一下抽象類的作用就迎刃而解啦。
3.程式碼應用舉例:
package BiscuitsDemo; public class BiscuitsTest { public static void main(String[] args) { //定義一個圓形燒餅物件 // Biscuits biscuits = new RoundedBiscuits(); //使用多型啦 RoundedBiscuits biscuits = new RoundedBiscuits(); PetaloidBiscuits petaloidBiscuits = new PetaloidBiscuits(biscuits); petaloidBiscuits.rounded(); } }
package BiscuitsDemo; /** * 燒餅介面,定義烙印圓形燒餅抽象方法 * @author * */ public interface Biscuits { //烙印圓形燒餅 void rounded(); }
package BiscuitsDemo; /** * 圓形燒餅類(常見燒餅) * @author * */ public class RoundedBiscuits implements Biscuits { @Override public void rounded() { System.out.println("新鮮出爐 圓乎乎的燒餅呀,圓乎乎"); } }
package BiscuitsDemo; /** * 燒餅裝飾抽象類 * @author * */ public abstract class DecoratorBiscuits implements Biscuits{ Biscuits biscuits; //定義燒餅介面物件,通過帶參構造方法封裝燒餅介面物件 public DecoratorBiscuits(Biscuits biscuits) { this.biscuits = biscuits; } } package BiscuitsDemo; /** * 新增了花瓣輪廓的燒餅燒餅類 * @author * */ public class PetaloidBiscuits extends DecoratorBiscuits{ public PetaloidBiscuits(Biscuits biscuits) { super(biscuits); } @Override public void rounded() { //呼叫實際幹活物件的rounded()方法 biscuits.rounded(); petaloid(); //新增花瓣輪廓,擴充套件功能 } //花瓣輪廓 private void petaloid() { System.out.println("像花一樣的燒餅來咯"); } }
執行結果:
最後ps:
1.介面(統一規範):
-
-
2、更加自然地使用多型
-
2.繼承:[也叫擴充](is-a 的關係)
-
(公共內容,放在父類)提高程式碼重用性,
-
(方便修改)提高維護性
-
類與類之間有了關係,多型的前提
3.重寫,方法重寫又稱[方法覆蓋]:子類重寫父類的方法。
重寫好處:重寫實現類的擴充,子類擁有了一種選擇權:繼承父類的方法實現細節,或者自己重寫方法實現細節覆蓋原有的方法的細節。(如果例項化子類物件,則呼叫的方法是子類重寫的方法。)
當子類可繼承父類,子類便擁有了父類的屬性和方法,就不用再編寫同樣的方法,但是想擁有自己的實現方式,就需要重寫覆蓋繼承來自父類的方法。
參考資料:https://www.imooc.com/article/24027 (Java設計模式(9)----------裝飾器模式)