在平常開發工做中,適當的使用一些設計模式,可讓代碼擴展性更強,能更好地擁抱變化,讓代碼更加優雅。本文主要介紹設計模式中的裝飾模式,並附上測試示例 Demo 供你們參考。編程
裝飾模式(Decorator Pattern)容許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是做爲現有的類的一個包裝。設計模式
裝飾模式能夠在運行時,在不修改原有代碼的前提下,動態地爲對象添加或移除指定的業務邏輯,比起繼承,採用裝飾模式讓代碼更據擴展性,更爲靈活,避免了繼承致使的代碼耦合。ide
裝飾模式的設計理念是:對修改關閉,對擴展開放;面對接口編程。測試
我的有時間會本身煮湯(這不是重點哈,只是恰好有這麼一個場景適合採用裝飾模式,所以也就拿來作例子了),在煮湯的過程當中,咱們須要添加不一樣的食材,就拿涼瓜排骨湯來講吧,須要的食材有排骨、涼瓜、大豆、食用鹽、水等,固然根據不一樣人的不一樣喜愛,能夠添加其餘的食材。以上說到的這些食材都是製做「涼瓜排骨湯」所必須的,沒有它們的點綴,湯喝起來也就不是那個味道了,這裏的點綴咱們能夠理解爲裝飾,是食材裝飾了「涼瓜排骨湯」,也就是說食材是裝飾者,而「涼瓜排骨湯」是被裝飾的對象。UML 圖以下:this
從上面的 UML 圖能夠看出,菜式類 Dish 和 食材抽象類 AbSeasoning 都須要實現食材接口 IMaterial 。菜式類 Dish 定義了一個屬性 name ,用於存儲菜式名稱,食材抽象類 AbSeasoning定義了一個食材引用 material 、食材名稱 name 和食材份量 weight ,分別用於存儲食材引用、食材名稱和食材份量。食材類 Seasoning 則須要繼承食材抽象類 AbSeasoning ,菜式類 Dish 和食材類 Seasoning 都須要實現各自獲取食材的方法 getStuff。在運行的過程當中,只須要把菜式賦給食材的食材引用便可,若是後續還須要添加其餘的食材,能夠把最後一次添加的食材賦給新食材的食材引用便可達到動態添加的效果。spa
IMaterial 食材接口類(裝飾者接口)設計
package decorator; public interface IMaterial { public String getStuff(); }
Dish 菜式類(被裝飾對象)3d
package decorator; public class Dish implements IMaterial { private String name; @Override public String getStuff() { return this.getName(); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
AbSeasoning 食材抽象類(裝飾者抽象類)code
package decorator; public abstract class AbSeasoning implements IMaterial { private IMaterial material; private String name; private String weight; public IMaterial getMaterial() { return material; } public void setMaterial(IMaterial material) { this.material = material; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getWeight() { return weight; } public void setWeight(String weight) { this.weight = weight; } }
Seasoning 食材類(裝飾者)對象
package decorator; public class Seasoning extends AbSeasoning { @Override public String getStuff() { return this.getMaterial().getStuff() + "\n" + this.getName() + ":" + this.getWeight(); } }
TestMain 測試類
package test; import decorator.AbSeasoning; import decorator.Dish; import decorator.Seasoning; public class TestMain { public static void main(String[] args) { Dish dish = new Dish(); dish.setName("涼瓜排骨湯"); AbSeasoning spareribs = new Seasoning(); spareribs.setName("排骨"); spareribs.setWeight("500g"); spareribs.setMaterial(dish); AbSeasoning bitterGourd = new Seasoning(); bitterGourd.setName("涼瓜"); bitterGourd.setWeight("200g"); bitterGourd.setMaterial(spareribs); AbSeasoning soybean = new Seasoning(); soybean.setName("大豆"); soybean.setWeight("50g"); soybean.setMaterial(bitterGourd); AbSeasoning salt = new Seasoning(); salt.setName("食用鹽"); salt.setWeight("5g"); salt.setMaterial(soybean); AbSeasoning water = new Seasoning(); water.setName("水"); water.setWeight("500ml"); water.setMaterial(salt); System.out.println(water.getStuff()); } }
測試結果