您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java怎么通過裝飾器模式擴展系統功能”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java怎么通過裝飾器模式擴展系統功能”文章能幫助大家解決問題。
裝飾模式可以在不改變一個對象本身功能的基礎上給對象增加額外的新行為,在現實生活中,這種情況也到處存在,例如一張照片,我們可以不改變照片本身,給它增加一個相框,使得它具有防潮的功能,而且用戶可以根據需要給它增加不同類型的相框,甚至可以在一個小相框的外面再套一個大相框。
裝飾模式是一種用于替代繼承的技術,它通過一種無須定義子類的方式來給對象動態增加職責,使用對象之間的關聯關系取代類之間的繼承關系。在裝飾模式中引入了裝飾類,在裝飾類中既可以調用待裝飾的原有類的方法,還可以增加新的方法,以擴充原有類的功能。
裝飾模式結構圖:
Component(抽象構件):它是具體構件和抽象裝飾類的共同父類,聲明了在具體構件中實現的業務方法,它的引入可以使客戶端以一致的方式處理未被裝飾的對象以及裝飾之后的對象,實現客戶端的透明操作。
ConcreteComponent(具體構件):它是抽象構件類的子類,用于定義具體的構件對象,實現了在抽象構件中聲明的方法,裝飾器可以給它增加額外的職責(方法)。
Decorator(抽象裝飾類):它也是抽象構件類的子類,用于給具體構件增加職責,但是具體職責在其子類中實現。它維護一個指向抽象構件對象的引用,通過該引用可以調用裝飾之前構件對象的方法,并通過其子類擴展該方法,以達到裝飾的目的。
ConcreteDecorator(具體裝飾類):它是抽象裝飾類的子類,負責向構件添加新的職責。每一個具體裝飾類都定義了一些新的行為,它可以調用在抽象裝飾類中定義的方法,并可以增加新的方法用以擴充對象的行為。
由于具體構件類和裝飾類都實現了相同的抽象構件接口,因此裝飾模式以對客戶透明的方式動態地給一個對象附加上更多的責任,換言之,客戶端并不會覺得對象在裝飾前和裝飾后有什么不同。裝飾模式可以在不需要創造更多子類的情況下,將對象的功能加以擴展。
場景:天氣太熱了,喝點兒冰水解解暑;加點兒檸檬片,讓果汁好喝點兒。
先定義一個喝水的接口
public interface Drink { /** * 喝水 */ void drink(); }
寫一個接口的實現
public class DrinkWater implements Drink { @Override public void drink() { System.out.println("喝水"); } }
一個簡單的裝飾器
public class DrinkDecorator implements Drink { private final Drink drink; public DrinkDecorator(Drink drink) { this.drink = drink; } @Override public void drink() { System.out.println("先加點兒檸檬片"); drink.drink(); } }
測試
public class DrinkMain { public static void main(String[] args) { Drink drink = new DrinkWater(); drink = new DrinkDecorator(drink); drink.drink(); } }
運行結果
先加點兒檸檬片
喝水
一個簡單的裝飾器模式例子就寫完了,這里只是先了解一下裝飾器模式。
大家應該都喝過奶茶吧,我經常喝的原味奶茶,里面可以添加配料,每增加一種配料,該奶茶的價格就會增加,要求計算一種奶茶的價格。
下面就可以使用裝飾器模式來模擬這種場景。
定義抽象構件類
/** * 奶茶 */ public interface MilkyTea { double cost(); }
定義具體構件類
/** * 珍珠奶茶 */ public class PearlMilkyTea implements MilkyTea{ @Override public double cost() { return 13.0; } }
定義抽象裝飾類
public abstract class MilkyTeaDecorator implements MilkyTea{ private MilkyTea milkyTea; public MilkyTeaDecorator(MilkyTea milkyTea){ this.milkyTea = milkyTea; } @Override public double cost() { return milkyTea.cost(); } }
定義具體裝飾類
/** * 椰果奶茶 */ public class CoconutDecorator extends MilkyTeaDecorator{ public CoconutDecorator(MilkyTea milkyTea) { super(milkyTea); } @Override public double cost() { System.out.println("添加椰果"); return super.cost() + 2.0; } } /** * 布丁奶茶 */ public class PuddingDecorator extends MilkyTeaDecorator{ public PuddingDecorator(MilkyTea milkyTea) { super(milkyTea); } @Override public double cost() { System.out.println("添加布丁"); return super.cost() + 1.5; } }
測試代碼
public class Client { public static void main(String[] args) { MilkyTea milkyTea = new PearlMilkyTea(); milkyTea = new CoconutDecorator(milkyTea); milkyTea = new PuddingDecorator(milkyTea); System.out.println(milkyTea.cost()); } }
運行結果
添加布丁
添加椰果
16.5
在客戶端代碼中,我們先定義了一個MilkyTea類型的具體構件對象milkyTea
,然后將milkyTea
作為構造函數的參數注入到具體裝飾類CoconutDecorator中,得到一個裝飾之后對象milkyTea
,再將裝飾了一次之后的milkyTea
對象注入另一個裝飾類PuddingDecorator中實現第二次裝飾,得到一個經過兩次裝飾的對象milkyTea,再調用milkyTea的cost()方法即可得到一杯既加了布丁又加了椰果的珍珠奶茶價格。
裝飾類和被裝飾類可以獨立發展,不會相互耦合。
相比于繼承,更加的輕便、靈活。
可以動態擴展一個實現類的功能,不必修改原本代碼
會產生很多的裝飾類,增加了系統的復雜性。
這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承易于出錯,排錯也很困難,對于多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為繁瑣。
在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
當不能采用繼承的方式對系統進行擴展或者采用繼承不利于系統擴展和維護時可以使用裝飾模式。不能采用繼承的情況主要有兩類:第一類是系統中存在大量獨立的擴展,為支持每一種擴展或者擴展之間的組合將產生大量的子類,使得子類數目呈爆炸性增長;第二類是因為類已定義為不能被繼承(如Java語言中的final類)。
關于“Java怎么通過裝飾器模式擴展系統功能”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。