好久沒有寫關於設計模式的博客了,實在是沒有太多的精力去寫。但我的以爲設計模式在咱們的平常開發中仍是挺重要的,它提升了軟件的可維護性。所以仍是有必要堅持學習設計模式,寫博客主要是爲了加深我對設計模式的理解。今天我要講的設計模式是裝飾者模式(Dectorator),它是結構型模式的一員。若是有什麼講的不正確的地方,但願各位大佬指正。java
首先,讓咱們思考下面的問題:設計模式
有這麼一家奶茶店,但願開發一個計算奶茶價格的軟件,當客戶點一杯奶茶,而且加入某幾樣配料時,須要及時的計算出這杯奶茶的價格,下面是奶茶和配料的價格。 原味奶茶:10 珍珠:2 椰果:3 巧克力:5 例子:若是用戶點椰果奶茶,那麼他的價格就是 原味奶茶+椰果=13。
當沒有學習過裝飾者模式時,我會給出下面的解決思路:ide
Ingredient.java:學習
public interface Ingredient { Integer price(); }
配料接口:全部的配料都要實現這個接口,該接口有一個價格方法。this
Chocolate.java:spa
public class Chocolate implements Ingredient { public Integer price() { return 5; } }
Coconut.java:設計
public class Coconut implements Ingredient { public Integer price() { return 3; } }
Pearl.java:code
public class Pearl implements Ingredient { public Integer price() { return 2; } }
以上的上個人配料的實現類,他們都實現了 Ingredient 接口,而且實現了 price 方法。對象
MilkTea.java:blog
import java.util.List; import java.util.ArrayList; public class MilkTea { private List<Ingredient> ingredientList = new ArrayList<>(); public void addIngredient(Ingredient ingredient) { ingredientList.add(ingredient); } public Integer countPrice() { Integer allPrice = 10; for (Ingredient ingredient : ingredientList) { allPrice += ingredient.price(); } return allPrice; } }
以上是奶茶類的實現,裏面有一個 ingredientList 成員變量,使用 addIngredient 就能夠增長配料,調用 countPrice 計算奶茶的價格。
TestMain.java:
public class TestMain { public static void main(String... args) { MilkTea milkTea = new MilkTea(); milkTea.addIngredient(new Chocolate()); System.out.println("巧克力奶茶:" + milkTea.countPrice()); MilkTea milkTea_1 = new MilkTea(); milkTea_1.addIngredient(new Coconut()); milkTea_1.addIngredient(new Pearl()); System.out.println("珍珠椰果奶茶:" + milkTea_1.countPrice()); } }
下面給出該實現的uml類圖。
定義:動態的給特定對象賦予新的功能.
類圖:
從上面的類圖咱們能夠總結出如下幾點:
1.實現裝飾者模式,咱們須要有一個公共接口,咱們的裝飾者和被裝飾者都須要繼承這個接口.
2.爲了更好地維護代碼,上面將被裝飾者的公共的代碼提取到了父類中,子類經過繼承這個父類能夠很容易的實現不一樣的特性.
3.在父類的接口中實現了 Material 接口,以保證裝飾者能夠被其餘裝飾者裝飾.
4.父類中有成員變量 Material ,以保證每一個裝飾者都知道本身裝飾的是什麼對象.
Material.java:
public interface Material { Integer price(); }
MilkTea.java:
public class MilkTea implements Material { @Override public Integer price() { return 10; } }
Ingredient.java:
public abstract class Ingredient implements Material { private Material material; public Ingredient(Material material) { this.material = material; } @Override public Integer price() { return material.price() + getPrice(); } public abstract Integer getPrice(); }
Chocolate.java:
public class Chocolate extends Ingredient { public Chocolate(Material material) { super(material); } @Override public Integer getPrice() { return 5; } }
Coconut.java:
public class Coconut extends Ingredient { public Coconut(Material material) { super(material); } @Override public Integer getPrice() { return 3; } }
Pearl.java:
public class Pearl extends Ingredient { public Pearl(Material material) { super(material); } @Override public Integer getPrice() { return 2; } }
MainTest.java:
public class MainTest { public static void main(String... args) { Material milkTea = new Chocolate(new MilkTea()); System.out.println("巧克力奶茶:" + milkTea.price()); Material milkTea_1 = new Coconut(new Pearl(new MilkTea())); System.out.println("珍珠椰果奶茶:" + milkTea_1.price()); } }