装饰(decorate)模式又称为包装(Wrapper)模式,顾名思义,装饰模式就是对XXX进行包装,使其功能,职责更加完善;说白了就是给对象增加新的功能,是继承关系的一个替代方案。
我们通常来使用继承来实现功能的扩展,如果这些需要扩展的功能很繁多,那么势必会增加系统的复杂性,使程序显得十分的“臃肿”,耦合度很高,同时,使用继承实现功能的扩展,我们必须可预见这些扩展功能,这些功能是编译时就确定的,是静态的。
思想:为一个对象已有的子类添加一些额外的职责。
代码实例:
抽象接口
public interface AbstractCar { public abstract void move(); }基础实现
public class CarImpl implements AbstractCar{ @Override public void move() { System.out.println("car is driving on the highway"); } }功能扩展(飞行)
public class FlyCar extends CarImpl { public void fly(){ System.out.println("car is driving in the air"); } @Override public void move() { super.move(); fly(); } }功能扩展(水行)
public class FlyAndSwimCar extends FlyCar { public void swim(){ System.out.println("car is driving in the water"); } @Override public void move() { super.move(); swim(); } }测试类
public class Tester { public static void main(String[] args) { AbstractCar car1 = new CarImpl(); car1.move(); System.out.println("------add fly function-----"); AbstractCar car2 = new FlyCar(); car2.move(); System.out.println("------add swiming function-----"); AbstractCar car3 = new FlyAndSwimCar(); car3.move(); } }输出
car is driving on the highway ------add fly function----- car is driving on the highway car is driving in the air ------add swiming function----- car is driving on the highway car is driving in the air car is driving in the water如果我们有更多的需求,这个继承体系会愈来愈大;这时,我们就可以使用装饰者模式。
代码实例
被装饰者
/** * 抽象汽车类,被装饰者 * @author Administrator * */ public interface Car { public abstract void move(); }装饰者
public abstract class CarDecorator implements Car { private Car car; public CarDecorator(Car car) { this.car = car; } @Override public void move() { this.car.move(); } }被装饰者初始装饰
public class CarImpl implements Car { /** * 被装饰者初始状态有些自己的装饰 */ @Override public void move() { System.out.println("car is moving on the highway"); } }水行装饰
public class SwimingCar extends CarDecorator { public SwimingCar(Car car) { super(car); } public void DrivingInWater(){ System.out.println("car is driving in the water"); } @Override public void move() { super.move(); DrivingInWater(); } }飞行装饰
public class FlyCar extends CarDecorator { public FlyCar(Car car) { super(car); } public void DrivingInAir(){ System.out.println("car is driving in the air"); } @Override public void move() { super.move(); DrivingInAir(); } }测试类
public static void main(String[] args) { Car car = new CarImpl(); car.move(); System.out.println("---------------"); CarDecorator fly = new FlyCar(car); fly.move(); System.out.println("---------------"); CarDecorator swiming = new SwimingCar(car); swiming.move(); System.out.println("---------------"); CarDecorator flyAndSwim = new FlyCar(swiming); flyAndSwim.move(); } }我们再来看下他的继承体系
Car |--CarDecorator |--FlyCar |--SwimingCar |--其他装饰 、 、 、 |--CarImpl由此可知、使用装饰模式他的继承体系不像单纯的使用继承那样庞大。
代码实例
被装饰者
/** * 定义被装饰者 * * @author Administrator * */ public abstract class Pancake { protected String name; public String getName() { return name; } public abstract double getPrice(); }装饰者
/** * 定义装饰者 * * @author Administrator * */ public abstract class PancakeDecorate extends Pancake { private Pancake pancake; public PancakeDecorate(Pancake pancake) { this.pancake = pancake; } @Override public String getName() { return this.pancake.getName(); } @Override public double getPrice() { return this.pancake.getPrice(); } }初始化装饰
public class PancakeInit extends Pancake { public PancakeInit(){ name = "煎饼"; } @Override public double getPrice() { return 8; } }生菜装饰
public class LettuceDecorate extends PancakeDecorate { public LettuceDecorate(Pancake pancake) { super(pancake); } @Override public String getName() { return super.getName()+" 加生菜"; } @Override public double getPrice() { return super.getPrice()+1; } }鸡蛋装饰
public class EggDecorate extends PancakeDecorate { public EggDecorate(Pancake pancake) { super(pancake); } @Override public String getName() { return super.getName()+"加鸡蛋"; } @Override public double getPrice() { return super.getPrice()+2; } }火腿装饰
public class HamDecorate extends PancakeDecorate { public HamDecorate(Pancake pancake) { super(pancake); } @Override public String getName() { return super.getName()+" 加火腿"; } @Override public double getPrice() { return super.getPrice()+2; } }测试类
public class Tester { public static void main(String[] args) { // 基本的煎饼 Pancake pancake = new PancakeInit(); System.out.println(pancake.getName() + " 价格:" + pancake.getPrice()); // 只加生菜 PancakeDecorate pd = new LettuceDecorate(pancake); System.out.println(pd.getName() + " 价格:" + pd.getPrice()); // 只加火腿 pd = new HamDecorate(pancake); System.out.println(pd.getName() + " 价格:" + pd.getPrice()); // 加鸡蛋,加火腿 pd = new HamDecorate(new LettuceDecorate(pancake)); System.out.println(pd.getName() + " 价格:" + pd.getPrice()); } }输出
煎饼 价格:8.0 煎饼 加生菜 价格:9.0 煎饼 加火腿 价格:10.0 煎饼 加生菜 加火腿 价格:11.0个人理解:装饰者模式的设计对扩展开放、对修改关闭,体现在如果我想扩展被装饰者的职责,无须修改装饰者抽象类,只需要继承装饰者抽象类,实现额外的装饰或者职责只需要对被装饰者进行包装即可。
如果你细心的话上面示例的调用类似于我们读取文件时的调用:
FileReader fr = new FileReader("a.txt"); BufferedReader br = new BufferedReader(fr);实际上Java 的I/O API就是使用装饰模式实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.
