基本要点
1、职责
- 动态的为一个对象增加新的功能
- 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀
2、实现细节
抽象构件角色(component):具体构建角色和装饰角色有相同的接口,这样,客户端就能以与真实对象相同的方式同装饰对象交互
例如:IO流中的InputStream、OutputStream、Reader、Writer
具体构件角色(真实对象,concreteComponent)
例如:IO流中的FileInputStream、FileOutputStream
装饰角色(Decorator):持有一个抽象构件的引用,装饰对象接受所有客户端请求,并且把这些请求转发给真实对象,这样就能在真实对象调用前后增加新的功能
例如:IO流中的FilterInputStream、FilterOutputStream
具体装饰角色(concreteDecorator):继承装饰角色,负责给真实对象增加新的责任
例如:IO流中的BufferedInputStream、BufferedOutputStream
3、优缺点
1)优点
- 降低了系统的耦合度,可以动态增加或删除对象的职责
- 比继承灵活,不会导致类个数的剧增
- 可以对一个对象进行多种装饰,创造出不同的组合
- 具体构建类(真实对象)和具体装饰类可以独立变化,用户可以根据自己的需要增加新的具体构建子类和具体装饰子类
2)缺点
- 会产生很多小对象,大量的小对象会占用内存,影响性能
- 装饰模式易出错,调试排查比较困难
4、装饰模式和桥接模式的区别
装饰模式是为了增加新的功能,桥接模式是为了处理多层继承结构(违背了单一职责原则),处理多维度变化的场景
5、实例演示
我们举一个建造汽车的例子,我们现在想给汽车加上飞行功能、水里游走功能
/**
* 抽象构件角色(component)
*/
public interface ICar {
void move();
}
/**
* 具体构件角色(真实对象,concreteComponent)
*/
class Car implements ICar {
@Override
public void move() {
System.out.println("普通汽车,陆地上跑");
}
}
/**
* 装饰角色(Decorator)
*/
class SuperCar implements ICar {
// 装饰角色需要持有一个抽象构件的引用
protected ICar car;
public SuperCar(ICar car) {
this.car = car;
}
@Override
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 SwimCar extends SuperCar {
public SwimCar(ICar car) {
super(car);
}
public void swim() {
System.out.println("水里游");
}
@Override
public void move() {
super.move();
swim();
}
}
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("增加水里游和天上飞-----------");
SwimCar swimCar = new SwimCar(flyCar);
swimCar.move();
}
}
运行结果如下
如有错误,欢迎指正