定义
- 在不修改原对象的情况下, 拓展对象的功能
- 符合”组合优于继承” 的设计原则
分离开核心功能与非核心的扩展功能。我们可以将核心功能放到实际类上,其他非核心装饰类的功能放到装饰类上
对比
不修改原对象, 而拓展对象的功能, 可以使用两种方式
对类进行继承, 然后在子类中拓展功能, 最后使用子类
-
继承
当功能种类多, 功能之间的组合多的时候, 需要每一种功能组合的情况都创建一个子类, 容易造成子类爆炸
组合
功能的实现可以通过包装类, 对于继承中容易造成子类爆炸的功能组合情况, 可以通过嵌套包装来实现
核心角色
- Component接口
在我们上面的例子中,Component接口相当于汽车接口,所有的被包装类、包装类,都继承于这个接口。
- ConcreteComponent类
ConcreteComponent类是被包装的实现类。在例子中,奔驰汽车、宝马汽车、特斯拉汽车都属于这个角色。
- Decorator抽象类
所有的包装类,都继承自Decorator抽象类,而Decorator类又实现了Component接口,这么做是为了实现多层嵌套包装。
- ConcreteDecorator类
具体的包装类,用于扩充被包装类的功能,比如例子中的自动驾驶功能、飞行功能扩展
示例
Component 角色 —> 接口, 原始类的接口
public interface Car {
void run();
}
ConcreteComponent 角色 —> 接口的实现类, 既各个原始类
public class BenzCar implements Car {
@Override
public void run() {
System.out.println("奔驰开车了!");
}
}
public class BmwCar implements Car {
@Override
public void run() {
System.out.println("宝马开车了!");
}
}
public class TeslaCar implements Car {
@Override
public void run() {
System.out.println("特斯拉开车了!");
}
}
Decorator 角色 —> 装饰器的抽象类
public class CarDecorator implements Car {
protected Car decoratedCar;
public CarDecorator(Car decoratedCar) {
this.decoratedCar = decoratedCar;
}
public void run() {
decoratedCar.run();
}
}
注意:
- 装饰器的抽象类一定要实现原始类的接口
- 让每一个装饰器本身也可以被更外层的装饰器所包装,包装的方式就是把Car对象作为参数传递给构造器
- 目的是为了实现嵌套装饰
功能一
public class AutoCarDecorator extends CarDecorator {
public AutoCarDecorator(Car decoratedCar) {
super(decoratedCar);
}
@Override
public void run() {
decoratedCar.run();
autoRun();
}
private void autoRun() {
System.out.println("开启自动驾驶");
}
}
功能二
public class FlyCarDecorator extends CarDecorator {
public FlyCarDecorator(Car decoratedCar) {
super(decoratedCar);
}
@Override
public void run() {
decoratedCar.run();
fly();
}
private void fly() {
System.out.println("开启飞行汽车模式");
}
}
客户端 —> 包装和嵌套包装调用
public class Client {
public static void main(String[] args) {
Car benzCar = new BenzCar();
Car bmwCar = new BmwCar();
Car teslaCar = new TeslaCar();
//创建自动驾驶的奔驰汽车
CarDecorator autoBenzCar = new AutoCarDecorator(benzCar);
//创建飞行的、自动驾驶的宝马汽车 --> 嵌套包装
CarDecorator flyAutoBmwCar = new FlyCarDecorator(new AutoCarDecorator(bmwCar));
benzCar.run();
bmwCar.run();
teslaCar.run();
autoBenzCar.run();
flyAutoBmwCar.run();
}
}