在平常开发工做中,适当的使用一些设计模式,可让代码扩展性更强,能更好地拥抱变化,让代码更加优雅。本文主要介绍设计模式中的装饰模式,并附上测试示例 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()); } }
测试结果