装饰模式概述
虽然现在买房子很多时候都自带装修,但是也有毛坯房(不带装修),而我们并不可能直接就住进一间毛坯房,肯定要进行一番装修(装饰),而房子就是我们的待装饰对象,这个简单的例子就是装饰者模式的主要概念。(在调用对象的具体方法前,对被装饰者进行装饰后再调用)
示例
张三想买车,但是预算有限,只买了一辆五菱宏光,但是他又非常喜欢和别的豪车拼速度,所以偷偷地给自己的五菱宏光的装上了涡轮引擎,所以每次起步加速都是用涡轮强化了加速功能。用装饰者模式描述这一功能实现。
UML图
示例解析
抽象类Car,拥有加速和停止功能,五菱宏光是具体的实现类,装饰者(CarDecorator)持有被装饰对象(Car),同时实现了Car的抽象方法,在调用Car的加速功能之前,对加速功能进行了强化(装饰),但是对停车功能不作改动.
示例代码
抽象Car
public abstract class Car {
public abstract void speedup();
public abstract void stop();
}
具体实现类
public class WuLingHongGuang extends Car{
@Override
public void speedup() {
System.out.println("五菱宏光加速");
}
@Override
public void stop() {
System.out.println("五菱宏光停车");
}
}
装饰器类
public class CarDecorator extends Car {
private Car car;
public void setCar(Car car) {
this.car = car;
}
@Override
public void speedup() {
System.out.println("加速前强化");
car.speedup();
}
@Override
public void stop() {
car.stop();
}
}
调用
Car car = new WuLingHongGuang();
CarDecorator carDecorator = new CarDecorator();
carDecorator.setCar(car);
carDecorator.speedup();
carDecorator.stop();
输出
加速前强化
五菱宏光加速
五菱宏光停车
装饰模式优缺点
优点
- 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
- 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。
缺点
- 装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。
适用场景
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。