装饰器模式
也叫包装器模式,降低系统的耦合度,可以动态的增加或者删除对象的职责,并使得需要装饰的具体构建类和具体装饰器类可以独立变化,以便增加新的具体构建类和具体的装饰器类
动态的为一个对象增加新的功能
装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。
使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀
实现细节
Component抽象构件角色:真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。
ConcreteComponent具体构件角色(真实对象):io流中的FileInputStream、FileOutputStream
Decorator装饰角色:持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
ConcreteDecorator具体装饰角色:负责给构件对象增加新的责任。
使用场景
- IO中输入流和输出流的设计
- Swing包中图形界面构件功能
- Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类增强了request对象的功能。
- Struts2中,request,response,session对象的处理
优点
- 扩展对象的功能,比继承灵活,不会导致类的数量急剧增加
- 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
- 具体构建类具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构建子类和具体装饰子类
缺点
- 产生很多小对象。大量小对象占据内存,一定程度上影响性能
- 装饰模式易于出错,调试排查比较麻烦.
案例
- 抽象构建角色component,cook的功能
public interface Cook {
public void cookDinner();
}
- 具体的构建角色,中国厨师
public class ChineseCook implements Cook {
public void cookDinner() {
System.out.println("中国人做晚饭");
}
}
- Decorator装饰角色,扩展cook的功能,持有cook的角色
public abstract class AbstractCookDecorator implements Cook {
protected Cook cook;
}
- 具体的装饰角色,实现具体的扩展的cook的功能
public class WashHandsCook extends AbstractCookDecorator {
public WashHandsCook(Cook cook) {
this.cook = cook;
}
public void cookDinner() {
System.out.println("先洗手");
cook.cookDinner();
}
}
public class WashHeadsCook extends AbstractCookDecorator {
public WashHeadsCook(Cook cook) {
this.cook = cook;
}
public void cookDinner() {
System.out.println("先洗头");
cook.cookDinner();
}
}
- 具体使用
public class Demo {
public static void main(String[] args) {
Cook cook = new ChineseCook();
Cook cook1 = new WashHandsCook(cook);
cook1.cookDinner();
System.out.println("-------------------------");
Cook cook2 = new WashHeadsCook(cook);
cook2.cookDinner();
System.out.println("-------------------------");
Cook cook3 = new WashHeadsCook(cook1);
cook3.cookDinner();
System.out.println("-------------------------");
}
}
其实说白了就是通过调用构造函数,一层一层去包装对象,扩展其中的功能。