在日常開發(fā)工作中,適當(dāng)?shù)氖褂靡恍┰O(shè)計(jì)模式,可以讓代碼擴(kuò)展性更強(qiáng),能更好地?fù)肀ё兓?,讓代碼更加優(yōu)雅。本文主要介紹設(shè)計(jì)模式中的裝飾模式,并附上測試示例 Demo 供大家參考。
定義
裝飾模式(Decorator Pattern)允許向一個(gè)現(xiàn)有的對象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它是作為現(xiàn)有的類的一個(gè)包裝。
個(gè)人理解
裝飾模式可以在運(yùn)行時(shí),在不修改原有代碼的前提下,動(dòng)態(tài)地為對象添加或移除指定的業(yè)務(wù)邏輯,比起繼承,采用裝飾模式讓代碼更據(jù)擴(kuò)展性,更為靈活,避免了繼承導(dǎo)致的代碼耦合。
裝飾模式的設(shè)計(jì)理念是:對修改關(guān)閉,對擴(kuò)展開放;面對接口編程。
示例介紹
個(gè)人有時(shí)間會(huì)自己煮湯(這不是重點(diǎn)哈,只是剛好有這么一個(gè)場景適合采用裝飾模式,因此也就拿來做例子了),在煮湯的過程中,我們需要添加不同的食材,就拿涼瓜排骨湯來說吧,需要的食材有排骨、涼瓜、大豆、食用鹽、水等,當(dāng)然根據(jù)不同人的不同喜好,可以添加其他的食材。以上說到的這些食材都是制作“涼瓜排骨湯”所必須的,沒有它們的點(diǎn)綴,湯喝起來也就不是那個(gè)味道了,這里的點(diǎn)綴我們可以理解為裝飾,是食材裝飾了“涼瓜排骨湯”,也就是說食材是裝飾者,而“涼瓜排骨湯”是被裝飾的對象。UML 圖如下:
從上面的 UML 圖可以看出,菜式類 Dish 和 食材抽象類 AbSeasoning 都需要實(shí)現(xiàn)食材接口 IMaterial 。菜式類 Dish 定義了一個(gè)屬性 name ,用于存儲(chǔ)菜式名稱,食材抽象類 AbSeasoning定義了一個(gè)食材引用 material 、食材名稱 name 和食材分量 weight ,分別用于存儲(chǔ)食材引用、食材名稱和食材分量。食材類 Seasoning 則需要繼承食材抽象類 AbSeasoning ,菜式類 Dish 和食材類 Seasoning 都需要實(shí)現(xiàn)各自獲取食材的方法 getStuff。在運(yùn)行的過程中,只需要把菜式賦給食材的食材引用即可,如果后續(xù)還需要添加其他的食材,可以把最后一次添加的食材賦給新食材的食材引用即可達(dá)到動(dòng)態(tài)添加的效果。
示例代碼
IMaterial 食材接口類(裝飾者接口)
package decorator;public interface IMaterial { public String getStuff(); }
Dish 菜式類(被裝飾對象)
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 食材抽象類(裝飾者抽象類)
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()); } }
測試結(jié)果
歡迎轉(zhuǎn)載,轉(zhuǎn)載必須標(biāo)明出處
http://www.cnblogs.com/rexfang/p/6748313.html