一.装饰器模式要解决的问题
装饰器模式是为了给处于运行时的对象添加某些功能。
通常扩展一个类的功能是通过继承或实现接口,这样在编译期该类的所有实例(对象)都具有扩展的功能,但是在运行期若为该类的某个对象添加某个功能则需用到装饰器模式。
二.装饰器模式用例(Java)
假设要生产汽车,我们可定义一个Car接口,接口中有个组装车的方法,然后可以组装一个拥有基本功能的基础版车型BasicCar,不久后客户需求升级,需要运动版SportCar和豪华版车型LuxuryCar,这时又在基础版基础上扩展出SportCar和LuxuryCar(通过继承),当实际生产时(程序运行期)客户又要求豪华运动版车型,此时实现起来就变的有些复杂了,此时应该考虑装饰器模式。
1.基础接口Car(Component Interface)
interface Car { void assemble(); }
2.基础接口的实现类BasicCar(Component Implementation)
class BasicCar implements Car { @Override public void assemble() { System.out.print("Basic Car."); } }
3.基础接口的装饰器类CarDecorator(Decorator)
为了能让子装饰器能够继承CarDecorator,Car变量访问范围为protected。
class CarDecorator implements Car { protected Car car; public CarDecorator(Car c){ this.car=c; } @Override public void assemble() { this.car.assemble(); } }
4.具体的装饰器类SportsCar和LuxuryCar(Concrete Decorators)
class SportsCar extends CarDecorator { public SportsCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Adding features of Sports Car."); } } class LuxuryCar extends CarDecorator { public LuxuryCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Adding features of Luxury Car."); } }
5.装饰器模式测试DecoratorPatternTest
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(); }
}
三.装饰器模式适用场景及要点
优势:在提供运行时修改对象特性的能力以及提高程序伸缩性上比较有帮助。
劣势:该设计模式用了很多相似的对象,如本例中的Concrete Decorators。
Java IO中的FileReader和BufferedReader用到了装饰器模式。