我想有新功能,但我不想改自己的代码,那就装饰一下吧。
装饰模式
装饰模式可以在不改变一个对象本身的基础上,给对象增加额外的新行为。
角色
Component(抽象构件)
抽象构件定义了对象的接口,可以给这些对象动态增加职责(方法)。抽象构件是具体构建和抽象装饰类的共同父类,它声明了在具体构件中实现的业务方法,它的引入能够使客户端以一致的方式处理未被装饰的对象以及装饰后的对象,实现客户端的透明操作。
Concrete Component(具体构件)
具体构件定义了具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类)
抽象装饰类使抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。
Concrete Decorator(具体装饰类)
具体装饰类是抽象装饰类的子类,负责向构件添加新的职责。
类图
实例
定义抽象构件
1 2 3
| public interface Shape { void draw(); }
|
定义具体构件
1 2 3 4 5 6
| public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }
|
1 2 3 4 5 6
| public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } }
|
定义抽象装饰类
1 2 3 4 5 6 7 8 9 10 11
| public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) { this.decoratedShape = decoratedShape; }
public void draw() { decoratedShape.draw(); } }
|
定义具体装饰类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); }
@Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); }
public void setRedBorder(Shape decoratedShape) { System.out.println("Border Color: Red"); } }
|
客户端测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Client { public static void main(String[] args) { Shape circle = new Circle(); Shape rectangle = new Rectangle(); System.out.println("Current state of shape: "); circle.draw(); rectangle.draw();
ShapeDecorator redCircle = new RedShapeDecorator(circle); ShapeDecorator redRectangle = new RedShapeDecorator(rectangle); System.out.println("\nCurrent state of shape: "); redCircle.draw(); redRectangle.draw(); } }
|
运行结果为
1 2 3 4 5 6 7 8 9
| Current state of shape: Shape: Circle Shape: Rectangle
Current state of shape: Shape: Circle Border Color: Red Shape: Rectangle Border Color: Red
|
给对象增加行为的两种方式
继承机制
通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法,但这种方法是静态的,用户不能控制增加行为的方式和时机。
关联机制
关联机制是装饰模式的核心,是更加灵活的方法,即将一个类的对象嵌入另一个新对象中,由另一个对象来决定是否调用嵌入对象的行为并扩展新的行为,这个新的对象即为装饰器(Decorator)。
为了使装饰器与它所装饰的对象对客户端透明,装饰器类和被装饰的类必须实现相同的接口,客户端使用时无须关心一个类的对象是否被装饰过,可以一致性地使用未被装饰的对象以及装饰过的对象。已经被装饰过的对象可以继续作为新的被装饰的对象进行装饰,这种透明性可以是我们递归的嵌套多个装饰。
模式优缺点
优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但装饰模式可以提供比继承更多的灵活性;
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为;
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象;
- 具体构件类与具体装饰类可独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,符合开闭原则。
缺点
- 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式不同,而不是它们的类或者属性值不同,同时还将产生很多具体装饰类,将会增加系统的复杂度,加大学习与理解的难度;
- 这种比继承更加灵活的特性,也同时意味着装饰模式比继承更容易出错,排错也很困难,对于多次装饰的对象,调试时寻找错误需要逐级排查。