装饰模式的出现个人认为主要是为了解决继承的不足,比如有的时候我们只想给一类对象动态的加上一些行为,如果我们用小继承,就必须修改超类,但一旦修改了超类,就会导致所有继承它的类都有了这个方法,然而并不是所有类都需要。
这时装饰模式就能很好的解决问题。
装饰模式最核心的一点就是被装饰类和装饰类继承同一个超类。其实这个很好理解,一个类被装饰后还是它自己。
一个简单的例子:我们都知道汽车能跑,于是我们抽象出一个超类car有run方法,现在我有一个汽车能飞,怎么办?这时增加一个装饰类FlyCarDecorator继承car来实现fly方法。这样我们只需要让装饰类FlyCarDecorator来让汽车实现fly的功能即可。具体实现也很简单,就是装饰类的构造函数里传入需要被装饰的car对象即可。
这样设计后,如果我们需要一个汽车能swim,不需要修改之前的代码,只需要新增一个SwimCarDecorator的装饰类即可。这样就遵守了开放(易于扩展)封闭(不修改原来的代码)原则。
如果我们的汽车要既能fly又能swim呢?简单!只需要先让FlyCarDecorator装饰它,再让SwimCarDecorator装饰它就行了~~
装饰模式在实际的应用中,比如java.io包里的FilterInputStream是一个抽象装饰者,它下面的BufferedInputStream,LineNumberInputStream都是具体的装饰者,可以装饰InputStream对象。
下面是一个完整的代码例子
package com.decorator; public abstract class Car { public void run(){ System.out.println("i can run!"); } public String getInfo(){ return "i can run"; } public void show() { this.run(); } }
package com.decorator; public class CarDecorator extends Car { public Car car; public CarDecorator(Car car) { this.car = car; } }
package com.decorator; public class FlyCarDecorator extends CarDecorator { public FlyCarDecorator(Car car){ super(car); } @Override public void show() { super.car.show(); this.fly(); } public void fly() { System.out.println("i can fly !"); } public String getInfo(){ return car.getInfo() + ",fly"; } }
package com.decorator; public class SwimCarDecorator extends CarDecorator { public SwimCarDecorator(Car car) { super(car); } @Override public void show() { super.car.show(); this.swim(); } public void swim() { System.out.println("i can swim!"); } public String getInfo(){ return car.getInfo() + ",swim"; } }
package com.decorator; /** * 测试类 */ public class DecoratorTest { public static void main(String[] args) { Car car = new RunCar(); Car flycar = new FlyCarDecorator(car); flycar.show(); System.out.println("--------------"); Car swimflycar = new SwimCarDecorator(flycar); swimflycar.show(); System.out.println(swimflycar.getInfo()); } }