装饰模式职责
- 动态的为一个对象增加新的功能
- 装饰模式是一种用于代替继承的技术, 无需通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀
装饰模式实现细节
- 1),Component 抽象构建角色
- 真实对象和装饰对象有相同的接口 , 这样,客户端对象就能就能以与真实对象相同的放式装饰对象交互
- 2),ConcreteComponent具体构建角色(真实对象)
- 类似 IO 流中的 FileInputStream , FileOutputStream
- 3),Decorator装饰对象
- 持有一个抽象构建的引用, 装饰对象接受接受客户端的请求,并把这些请求转发给真实的对象 。 这样 ,就能在真实对象调用前后增加新的功能 。
- 4),ConcreteDecorator 具体装饰对象
- 负责给构件对象增加新的责任
uml类图,如下
代码如下
package com.tuogo.decorate;
/**
* Component 抽象构建角色
*/
public interface MyCar {
void run();
}
//创建ConcreteComponent 具体构建角色(真实对象)
class RealCar implements MyCar{
@Override
public void run() {
System.out.println("普通的汽车跑");
}
}
//ConcreteDecorator 具体装饰对象
class DecorateCar implements MyCar{
private MyCar myCar;
public DecorateCar(MyCar myCar) {
this.myCar = myCar;
}
@Override
public void run() {
myCar.run();
}
}
//天上飞的汽车
class FlyCar extends DecorateCar {
public FlyCar(MyCar myCar) {
super(myCar);
}
private void fly(){
System.out.println("汽车可以天上飞");
}
@Override
public void run() {
super.run();
fly();
}
}
//水上游的汽车
class WaterCar extends DecorateCar {
public WaterCar(MyCar myCar) {
super(myCar);
}
private void water(){
System.out.println("汽车可以在水上游");
}
@Override
public void run() {
super.run();
water();
}
}
创建客户端进行测试
public class Client {
public static void main (String[] args) {
//创建真实角色
RealCar car = new RealCar();
car.run();
System.out.println("给车添加飞 -------");
//增加天上飞的属性
FlyCar car1 = new FlyCar(car);
car1.run();
System.out.println("给车添加游 -------");
//增加水上游
WaterCar car2 = new WaterCar(car);
car2.run();
System.out.println("车 就可以跑 又 可以游-----");
WaterCar car3 = new WaterCar(new FlyCar(car));
car3.run();
}
}
开发中使用的场景
- IO 中输入流和输出流的设计
- SWING 包中图形界面构件功能
- Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper , HttpServletRequestWrapper类,增强了request对象的功能。
- Struts2中 ,request,response,session 对象的处理
总结
- 装饰模式(Decorator) 也叫包装器模式(Wrapper)
- 装饰器模式降低了系统的耦合度,可以动态增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
优点
- 扩展对象功能,比继承灵活,不会导致类个数急剧增加
- 可以对一个对象进行多次装饰, 创造出不同行为的组合, 得到功能更加强大的对象
- 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构建子类和具体装饰子类。
缺点
- 产生许多小对象,大量小对象占据内存,一定程度上影响性能
- 展示模式易于出错,调试排查比较麻烦