好久没有写关于设计模式的博客了,实在是没有太多的精力去写。但我的以为设计模式在咱们的平常开发中仍是挺重要的,它提升了软件的可维护性。所以仍是有必要坚持学习设计模式,写博客主要是为了加深我对设计模式的理解。今天我要讲的设计模式是装饰者模式(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()); } }