Java 示例中的装饰器设计模式
装饰器设计模式用于在运行时修改对象的功能。同时,同一类的其他实例不会受此影响,因此单个对象会获得修改后的行为。装饰器设计模式是结构设计模式之一(例如适配器模式、桥接模式、组合模式),使用抽象类或接口与组合来实现。
装饰器设计模式
我们使用继承或组合来扩展对象的行为,但这是在编译时完成的,并且适用于类的所有实例。我们不能在运行时添加任何新功能或删除任何现有行为——这就是装饰器模式发挥作用的时候。假设我们想要实现不同种类的汽车——我们可以创建接口 Car 来定义组装方法,然后我们可以拥有一辆基本车,进一步我们可以将它扩展为跑车和豪华车。实现层次结构将如下图所示。但如果我们想在运行时获得一辆同时具有跑车和豪华车功能的汽车,那么实现就会变得复杂,如果我们想进一步指定应该首先添加哪些功能,它会变得更加复杂。现在想象一下,如果我们有十种不同类型的汽车,使用继承和组合的实现逻辑将无法管理。为了解决这种编程情况,我们在 java 中应用装饰器模式。我们需要有以下类型来实现装饰器设计模式。
-
组件接口-定义将要实现的方法的接口或抽象类
Car
。在我们的例子中是组件接口。package com.journaldev.design.decorator; public interface Car { public void assemble(); }
-
组件实现- 组件接口的基本实现。我们可以使用
BasicCar
类作为组件实现。package com.journaldev.design.decorator; public class BasicCar implements Car { @Override public void assemble() { System.out.print("Basic Car."); } }
-
装饰器- 装饰器类实现组件接口,并且与组件接口具有 HAS-A 关系。子装饰器类应该可以访问组件变量,因此我们将保护此变量。
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(); } }
-
具体装饰器- 扩展基本装饰器功能并相应地修改组件行为。我们可以有具体装饰器类,如
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等。