一.概念
动态的给一个对象添加额外的职责。想要扩展功能的话,装饰者提供了一种有别于继承的另外一种选择。
二.UML
- Component(概念中提到的对象接口),也就是“被装饰者”。
- ConcreateComponent(未添加任何职责的,对象接口的子类)。
- Decorator(装饰者抽象类),扩张了对象接口的功能。
- ConcreteDrcorator(具体装饰类),具体怎么装饰对象接口的在这些类里面反映。
三.实例分析
家里买了一套房子,需要装修,考虑到预算只有这么多,不能采用全包的方式,于是采用将装修工作细化,以节省开销。
House
package com.zzy.decorator; /** * 被装修者-房子 * @author eason * */ public interface House { public void decorate(); }
BlankHouse
package com.zzy.decorator; /** * 未经装修的房子 * @author eason * */ public class BlankHouse implements House{ @Override public void decorate() { System.out.println("未经装修的房子"); } }
Decorator
package com.zzy.decorator; /** * 装修工抽象类 * @author eason * */ public class Decorator implements House{ private House house; public Decorator(House house) { this.house = house; } @Override public void decorate() { house.decorate(); } }
ElectricWirer
package com.zzy.decorator; /** * 电线工 * @author eason * */ public class ElectricWirer extends Decorator { public ElectricWirer(House house) { super(house); } @Override public void decorate() { super.decorate(); //自己的逻辑-具体怎么包装的写在super.decorate()的前后任何地方 System.out.println("已经装修完电线"); } }
Floorer
package com.zzy.decorator; /** * 地板工 * @author eason * */ public class Floorer extends Decorator { public Floorer(House house) { super(house); } @Override public void decorate() { super.decorate(); //自己的逻辑-具体怎么包装的写在super.decorate()的前后任何地方 System.out.println("已经装修完地板"); } }
WaterPiper
package com.zzy.decorator; /** * 水管工 * @author eason * */ public class WaterPiper extends Decorator { public WaterPiper(House house) { super(house); } @Override public void decorate() { super.decorate(); //自己的逻辑-具体怎么包装的写在super.decorate()的前后任何地方 System.out.println("已经装修完水管"); } }
TestDecorator
package com.zzy.decorator; /** * 测试类 * @author eason * */ public class TestDecorator { public static void main(String[] args) { //空白房子一个 House house = new BlankHouse(); //一层层装修 Decorator dec = new Floorer(new ElectricWirer(new WaterPiper(house))); dec.decorate(); } }
四.使用场景
- 为已有组件动态添加更多功能。
五.使用感受
- 将装饰功能的代码从Component里面提了出来,简化了Component。
- 客户端可以在运行时根据需要,选择需要的功能来包装Component。
- 继承是扩展功能的方式之一,但并不见得是达到弹性设计的最佳形方式。
- 组合和委托可用于在运行时动态地加上新的行为。装饰者模式实际上就是组合和委托。再次提到组合和委托,第一次提到是在策略模式 里面。
- 在日常的设计中,应该允许行为被扩展,而不需修改现有的代码。
- 装修者会导致设计中出现许多小对象,如果过度使用,会让程序变的复杂。