意图
动态给对象添加一些额外的职责。
动机
- 有时希望能给某个对象而不是整个类的所有对象添加一些功能。
- 继承机制不够灵活,不能控制方法增强的时机(比如英雄李白拿蓝Buff,或者红Buff,Buff持续是有时间限制的)。
- 一种较为灵活的方式是将对象(如李白)放入一个装饰对象(如Buff),由装饰对象在合适的时机对原对象(李白)的方法(如攻击力、冷却时间)进行增强。
模式结构
效果
优点
- 比静态继承更灵活
- 可以运用添加和分离的方法,在运行时增加和删除职责。
- 相比而言,继承机制要求每个添加的职责创建一个子类。
- 多个Decorator装饰的实例对象间可以混合匹配。
- 避免在层次结构高层的类有太多的特征
- 采用即用即付方式添加职责
- 最初的类的功能不会很复杂,而是逐渐给它添加功能,这样使得程序不会为了不必要的特征付出代价。
- 可以很容易定义新的Decorator类。
缺点
- Decorator与它的Component不一样
- Decorator是一个透明包装。从对象标识出发,被装饰的组件与组件本身是有差别的。
- 因此,使用装饰时候,不应该依赖对象标识。
- 执行过程有许多小的对象产生
- 这些小对象差别主要是它们相互连接的方式上,而不是属性上。
- 对于不熟悉这种设计的人员,排错很困难。
实现
- 接口的一致性
装饰对象Decorator的接口必须与它所装饰的组件Component接口是一致的。所以所有实际装饰对象ConcreteDecorator必须有一个公共父类Decorator(一般是作为抽象类) - 省略抽象的Decorator类
仅需要添加一个职责时候,抽象的Decorator类是不必要的,直接给出实际的装饰。 - 保持Component类的简单性
Component接口重要作用是保证一致性,这个接口的简单性是很重要的(应该集中于定义方法,而不是存储数据,对数据表示的定义应该延迟到子类中)。否则Component类太复杂,难以大量使用,并且会导致子类无太多功能。 - 改变对象外壳与改变对象内核
Decorator可以看作是对象的外壳,那么策略模式Strategy即可以视为对象的内核。
Todo - 理解策略模式之后,进行比较归纳总结。
案例
1. 汽车功能定义
public interface ICar {/*** 基本功能:移动*/void move();}
2. 普通汽车实现
public class Car implements ICar {/*** 实现基本功能:移动*/@Overridepublic void move() {System.out.println("陆地上跑");}}
3. 超级汽车抽象
/*** 超级汽车 -> 增强的功能定义** @author Jinhua*/public abstract class SuperCar implements ICar {/*** 拿到有基本功能汽车的引用*/private final ICar car;public SuperCar(ICar car) {this.car = car;}/*** 此处任然是移动功能,未进行方法增强*/@Overridepublic void move() {car.move();}}
4. 超级汽车实现
1) AI汽车
public class AiCar extends SuperCar {/*** 继续拿到抽象类的基本功能汽车引用,构造其属性** @param car 基本功能的汽车*/public AiCar(ICar car) {super(car);}public void autoMove() {System.out.println("自动跑");}/*** 对移动方法进行了增强*/@Overridepublic void move() {super.move();autoMove();}}
2) 飞行汽车
public class FlyCar extends SuperCar {public FlyCar(ICar car) {super(car);}public void fly() {System.out.println("天上飞");}@Overridepublic void move() {super.move();fly();}}
3) 水中汽车
public class WaterCar extends SuperCar {public WaterCar(ICar car) {super(car);}public void swim() {System.out.println("水里游");}@Overridepublic void move() {super.move();swim();}}
测试主类
public class Main {public static void main(String[] args) {System.out.println("基本功能");ICar iCar = new Car();iCar.move();System.out.println("---------------");System.out.println("增加新的功能:飞行");ICar flyCar = new FlyCar(iCar);flyCar.move();System.out.println("---------------");System.out.println("增加新的功能:水里游");ICar waterCar = new WaterCar(iCar);waterCar.move();System.out.println("---------------");System.out.println("增加两个新的功能,飞行,水里游");ICar waterCar2 = new WaterCar(new FlyCar(iCar));waterCar2.move();}}
运行结果:
基本功能陆地上跑---------------增加新的功能:飞行陆地上跑天上飞---------------增加新的功能:水里游陆地上跑水里游---------------增加两个新的功能,飞行,水里游陆地上跑天上飞水里游
