意图:
动态地给一个对象添加一些额外的职责,就增加功能而言,Decorator模式相比生成子类模式更为灵活
动机:
有时我们希望给某个对象而不是整个类添加一些功能。例如,一个图形用户界面工具箱允许你对任意一个用户界面组件添加一些特性,例如边框,或是一些行为,例如窗口滚动。一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框。我们称这个嵌入的对象为装饰 。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。
例如,假定有一个对象 Te x t Vi e w,它可以在窗口中显示正文。缺省的 Te x t Vi e w没有滚动
条,因为我们可能有时并不需要滚动条。当需要滚动条时,我们可以用 S c r o l l D e c o r a t o r添加滚
动条。如果我们还想在 Te x t Vi e w周围添加一个粗黑边框,可以使用 B o r d e r D e c o r a t o r添加。因
此只要简单地将这些装饰和 Te x t Vi e w进行组合,就可以达到预期的效果。
结构:
例子:
以往画布上画一个圆为例来说明装饰模式的使用
1 package designpatterns.strucural; 2 //抽象构件角色--Component 3 interface Shape { 4 void draw(); 5 } 6 //具体构件角色--Concrete Component 7 class Circle implements Shape { 8 9 @Override 10 public void draw() { 11 System.out.println("Shape: Circle"); 12 } 13 } 14 15 //装饰角色--Decorator 16 abstract class ShapeDecorator implements Shape{ 17 protected Shape decoratedShape; 18 19 public ShapeDecorator(Shape decoratedShape) { 20 this.decoratedShape = decoratedShape; 21 } 22 23 public void draw() { 24 decoratedShape.draw(); 25 } 26 } 27 28 //具体装饰角色--Concrete Decorator1 29 class RedShapeDecorator extends ShapeDecorator { 30 31 public RedShapeDecorator(Shape decoratedShape) { 32 super(decoratedShape); 33 } 34 35 @Override 36 public void draw() { 37 decoratedShape.draw(); 38 setRedBorder(decoratedShape); 39 } 40 41 private void setRedBorder(Shape decoratedShape) { 42 System.out.println("Border Color: Red"); 43 } 44 45 } 46 47 //具体装饰角色--Concrete Decorator2 48 class DottedLineShapeDecorator extends ShapeDecorator { 49 50 public DottedLineShapeDecorator(Shape decoratedShape) { 51 super(decoratedShape); 52 } 53 54 @Override 55 public void draw() { 56 decoratedShape.draw(); 57 setLineType(decoratedShape); 58 } 59 60 private void setLineType(Shape decoratedShape) { 61 System.out.println("Line type: dotted"); 62 } 63 64 } 65 66 //画布 67 class Canvas{ 68 void addshape(Shape shape){ 69 shape.draw(); 70 } 71 } 72 73 //客户端 74 public class Decorator { 75 76 public static void main(String[] args) { 77 78 Canvas canvas = new Canvas(); 79 Circle circle = new Circle(); 80 81 canvas.addshape(circle); 82 System.out.println(); 83 84 canvas.addshape(new RedShapeDecorator(circle)); 85 System.out.println(); 86 87 canvas.addshape(new DottedLineShapeDecorator(new RedShapeDecorator(circle))); 88 System.out.println(); 89 } 90 91 }
验证输出:
Shape: Circle
Shape: Circle
Border Color: Red
Shape: Circle
Border Color: Red
Line type: dotted
代码说明:
最终使用该组件的客户为Canvas,由于装饰和它装饰的组件接口一致,客户就可以随意组合调用
1、绘制圆
2、绘制红色的圆
3、用虚线绘制红色的圆
你还可以添加更多的装饰,使用时只需要将这些装饰和组件Circul进行组合,就可以达到想要的效果
参考:
Java与模式
设计模式:可复用面向对象软件的基础