设计初衷:我们使用继承或组合来扩展对象的行为,但这是在编译时完成的,它适用于类的所有实例。我们无法在运行时添加任何删除任何现有行为的新功能 - 这就是Decorator模式出现的时候
假设我们想要实现不同种类的汽车 -
我们可以创建界面Car来定义组装方法然后我们可以拥有一辆Basic汽车,我们还可以将它扩展到跑车和豪华轿车。
但是如果我们想要在运行时获得具有跑车和豪华车功能的汽车,那么实施变得复杂,如果我们想要指定哪些功能应该首先添加,它会变得更加复杂。现在想象一下,如果我们有十种不同类型的汽车,使用继承和组合的实现逻辑将无法管理。为了解决这种编程情况,我们在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.");
}
}
Decorator - Decorator类实现组件接口,它与组件接口具有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();
}
}
Concrete Decorators - 扩展基本装饰器功能并相应地修改组件行为。我们可以将具体的装饰器类作为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.");
}
}
装饰设计模式 - 重点
装饰器设计模式有助于提供运行时修改能力,因此更灵活。当选择的数量更多时,它易于维护和扩展。
装饰器设计模式的缺点是它使用了许多类似的对象(装饰器)。
装饰器模式在Java IO类中经常使用,例如FileReader,BufferedReader等。
对照学习
查看io源码和实例可以看到,装饰者模式的底层是对超类或者接口进行继承或实现,但是装饰者会将被被装饰者作为属性放在类中进行功能增强,并且在通过构造器传入具体的组件进行增强。这使得了它和单纯的继承相比,不需要一直继承来实现新功能,而造成代码冗余,或者子类爆炸,比如要实现一共有N个功能,需要子类实现,对于继承来说子类就需要实现创建这么多个子类
但是装饰者模式就只需要10个装饰组件和一个装饰类和一个被装饰者就可以实现。装饰者模式就是对继承的大优化
装饰者
继承