装饰器模式用于在程序运行时修改对象实例功能。同时不影响其他对象实例(指同一类的不同实例),因为可以修改特定实例的行为。装饰器模式是一种结构设计模式(structual design pattern,相似的还有适配器模式、桥接模式、组合模式),他使用抽象类或者接口,通过组合的方式来实现。
介绍
我们使用继承或者组合来扩展对象的行为,但这通常在编译时完成,且所有类实例都可用。我们不能在运行时新增或删除任何功能,这时候我们就应该想起使用装饰器模式
假设我们需要实现不同种类的汽车,我们创建一个Car的汽车接口来定义一个assemble的装配方法,然后我们可以有一个基础的小汽车,进一步的我们可以扩展这辆车为运动型车和豪华车。实现的层次图如下。
但是如果我们在程序运行时想获取一辆拥有运动车和豪华车功能的基础车。如果还要考虑哪些功能先被加入,实现将变得复杂。设想一下,如果我们有10种不同类型的车呢,就不可能用继承和组合的方式来实现和管理。为了解决这种编程场景,我们应该使用装饰器模式
我们需要有下列类型来实现装饰器模式
1.组件接口-这个接口或抽象类用来定义我们将要实现的方法,在这个例子中,就是Car这个接口
package com.journaldev.design.decorator;
public interface Car {
public void assemble();
}
2.组建实现-组件接口的基础实现类。这儿我们创建一个BasicCar类来作为基础实现
package com.journaldev.design.decorator;
public class CarDecorator implements Car {
protected Car car;
public CarDecorator(Car c){
this.car=c;
}
@Override
public void assemble() {
this.car.assemble();
}
}
3.装饰器-装饰器类实现的组件接口,且有一个HAS-A的关系。这个组件变量应被修饰为protected,这样可以被装饰器的子类访问
package com.journaldev.design.decorator;
public class CarDecorator implements Car {
protected Car car;
public CarDecorator(Car c){
this.car=c;
}
@Override
public void assemble() {
this.car.assemble();
}
}
4.具体的装饰器- 继承基础的装饰类,因此可以修改组件的行为。这儿我们创建两个装饰器类LuxuryCar 和 SportsCar.
package com.journaldev.design.decorator;
public class SportsCar extends CarDecorator {
public SportsCar(Car c) {
super(c);
}
@Override
public void assemble(){
super.assemble();
System.out.print(" Adding features of Sports Car.");
}
}
package com.journaldev.design.decorator;
public class LuxuryCar extends CarDecorator {
public LuxuryCar(Car c) {
super(c);
}
@Override
public void assemble(){
super.assemble();
System.out.print(" Adding features of Luxury Car.");
}
}
装饰器类图
测试类
package com.journaldev.design.test;
import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;
public class DecoratorPatternTest {
public static void main(String[] args) {
Car sportsCar = new SportsCar(new BasicCar());
sportsCar.assemble();
System.out.println("\n*****");
Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
sportsLuxuryCar.assemble();
}
}
可以看到我们在运行时创建不同类型的汽车对象,并且可以定义这些功能的执行顺序 程序输出如下
Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.
重要点
- 装饰器模式用于在运行时动态修改对象能力,增强了灵活性。可以更加容易的维护和扩展多个实现选择
- 装饰器模式的缺点时创建很多相似的对象(装饰器对象)
- 装饰器模式在
Java IO中被大量使用,比如FileReader和BufferedReader