类结构
UML类图
初步理解
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。本例中,原本只能画圈圈,但是装饰器对现有对象进行了装饰,我们可以画出有颜色的圈圈了。
代码理解
基础接口
public interface Shape { void draw(); }
基础的接口实现类(2个)
public class Circle implements Shape { @Override public void draw() { System.out.println("只能画个圈圈"); } } public class Rectangle implements Shape { @Override public void draw() { System.out.println("只能画个框框"); } }
进行扩展的装饰类
可以看到,这个抽象类实现了Shape接口,根据传入的参数决定画哪个东西,这个也是多态的体现。
public abstract class ShapeDecorator implements Shape { public Shape decoratedShape; //构造函数,给Shape属性赋值 public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
装饰类的具体实现
抽象类里面是有方法没有实现的,因此还需要实现。
构造函数与父类的其它成员(成员变量和成员方法)不同,它不能被子类继承。因此,在创建子类对象时,为了初始化从父类中继承来的成员变量,编译器需要调用其父类的构造函数。如果子类的构造函数没有显示地调用父类的构造函数,则默认调用父类的无参构造函数。但这里需要传参数,因此需要写一个显示的构造函数,里面调用父类的构造函数。
public class RedShapeDecorator extends ShapeDecorator { //构造函数 public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } //扩展的新功能。 private void setRedBorder(Shape decoratedShape){ System.out.println("现在可以染红:"+decoratedShape); } }
出于省事的目的,这里没有重写toString方法。
测试主方法
下面的示例中,有4行加了注释,这是多态的体现。任意两行选出来都能运行。因为核心的装饰功能,在RedShapeDecorator类中,得到了实现。
public class Demo { public static void main(String[] args) { Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); // Shape redCircle = new RedShapeDecorator(new Circle()); // Shape redRectangle = new RedShapeDecorator(new Rectangle()); // RedShapeDecorator redCircle = new RedShapeDecorator(new Circle()); // RedShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); System.out.println("看我接下来画什么:"); circle.draw(); System.out.println(); System.out.println("功能提升:"); redCircle.draw(); System.out.println(); System.out.println("功能提升:"); redRectangle.draw(); } }
运行结果:
看我接下来画什么: 只能画个圈圈 功能提升: 只能画个圈圈 现在可以染红:_2004装饰者模式.Circle@1b6d3586 功能提升: 只能画个框框 现在可以染红:_2004装饰者模式.Rectangle@4554617c
理解与总结:
- 一般的,我们为了扩展一个类经常使用继承方式实现,但是随着扩展功能的增多,子类会很膨胀,类的种类比较多。
- 为了解决这个问题,我们这里并没有选择扩展一个可以画红色圈圈的类,以及一个可以画红色框框的类,而是只使用了一个装饰类,就完成了上面可能用两个类才能完成的扩展,减少了类的种类。通过这个装饰的类,传入某个参数,就可以去调用具体某个类的draw方法,然后这个装饰的类内部进行了相应的功能扩展。