装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰模式的优缺点
优点
- 扩展对象功能比继承灵活,不会导致类的个数急剧增加
- 可以对一个对象进行多次修饰,创建出不同行为的组合,得到功能更加强大的对象
- 具体构建类和具体修饰类可以独立变化
缺点 - 产生很多小的对象。大量小的对象会占用内存,一定程度上影响性能
- 装饰模式容易出错,调试排查比较麻烦
实现细节
- Component抽象构件角色
真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互 - ConcreteComponent具体构件角色(真实对象)
io中的FileInputStream,FileOutputStream - Decorator装饰角色
持有一个抽象构件的引用。装饰对象接受客户端的请求,并把这些请求转发给真实的对象,这样就在真实的对象调用前后增加新的功能 - ConcreteDecorator具体装饰角色
负责给构件对象增加新的责任
案例
创建ICar接口,里面定义一个move方法
创建SupserCar,FlyCar(会飞的车),SwimCar(会游泳的车),AICar(自动车)
package decorator;
/**
* 抽象构建
* @author Administrator
*
*/
public interface ICar {
void move();
}
//ConcreteComponent 具体构件角色(真实对象)
class Car implements ICar {
public void move() {
System.out.println("陆地上跑!");
}
}
//Decorator装饰角色
class SuperCar implements ICar {
protected ICar car;
public SuperCar(ICar car) {
super();
this.car = car;
}
public void move() {
car.move();
}
}
//ConcreteDecorator具体装饰角色
class FlyCar extends SuperCar {
public FlyCar(ICar car) {
super(car);
}
public void fly(){
System.out.println("天上飞!");
}
@Override
public void move() {
super.move();
fly();
}
}
//ConcreteDecorator具体装饰角色
class WaterCar extends SuperCar {
public WaterCar(ICar car) {
super(car);
}
public void swim(){
System.out.println("水上游!");
}
@Override
public void move() {
super.move();
swim();
}
}
//ConcreteDecorator具体装饰角色
class AICar extends SuperCar {
public AICar(ICar car) {
super(car);
}
public void autoMove(){
System.out.println("自动跑!");
}
@Override
public void move() {
super.move();
autoMove();
}
}
创建测试类Client
package decorator;
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move();
System.out.println("增加新的功能,飞行----------");
FlyCar flycar = new FlyCar(car);
flycar.move();
System.out.println("增加新的功能,水里游---------");
WaterCar waterCar = new WaterCar(car);
waterCar.move();
System.out.println("增加两个新的功能,飞行,水里游-------");
WaterCar waterCar2 = new WaterCar(new FlyCar(car));
waterCar2.move();
}
}
测试结果
开发中使用的场景:
- IO中输入流和输出流的设计
- Servlet API 中提供了一个request对象的Decorator设计模式的默认实 现类HttpServletRequestWrapper,HttpServletRequestWrapper 类,增强了request对象的功能。
- Struts2中,request,response,session对象的处理
总结
装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新 的具体构建类和具体装饰类。
装饰模式和桥接模式的区别
两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。
桥接模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。装饰模式是为了增加新的功能。