定义:
Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
定义中很明确的告诉我们,装饰器模式可以代替继承extend,而且比继承更灵活,同样是为对象添加额外的职责,为什么装饰器模式要比继承更加优秀呢?
当我们想要扩展一个类的功能时,创建其子类是通常的做法,可是当功能越来越多时,你的子类也会越来越多,最后变得难以管理和复杂,而装饰器模式可以很好的解决这个痛点问题。
装饰器模式的组成
● Component 抽象构件
Component 是一个接口或者是抽象类,就是定义我们最核心的对象,即最原始的对象。
● ConcreteComponent 具体构件
ConcreteComponent 是最核心、最原始、最基本的接口或抽象类的实现,是被装饰者
● Decorator 装饰角色
一般是一个抽象类,实现Component接口或者抽象方法,其有一个 private 变量指向 Component 抽象构件。
● 具体装饰角色
ConcreteDecoratorA 和 ConcreteDecoratorB 是两个具体的装饰类,用来装饰被装饰者。
UML图
从这里我们可以看到,装饰类和被装饰类可以独立发展,不会相互耦合,我们可以动态的扩展一个类的功能、动态的撤销功能,还不会使代码过于膨胀。
例子
借用RUNOOB的例子来说明装饰器模式
1.UML图
2.创建Component接口 — shape
public interface Shape {
void draw();
}
3.创建ConcreteComponent实现类 — Circle、Rectangle
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
-------------------------------------------
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
4.创建Decorator装饰者 — ShapeDecorator
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
5.创建具体装饰角色 — RedShapeDecorator
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("Border Color: Red");
}
}
6.测试
public class Test{
public static void main(String[] args) {
Shape circle = new Circle();
//传入被装饰者进行装饰
ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
redCircle.draw();
}
}
总结
1.使用场景:
- 扩展一个类的功能,或给一个类增加附加功能。
- 动态地给一个对象增加功能、动态地撤销功能。
- 为一批兄弟类进行改装或加装功能,当然是首选装饰模式。
2.优点
1.相比继承,装饰者模式使代码耦合度降低,可以动态的增加、撤销类的扩展功能。
2.结构分明,不会出现子类过多时带来的不便。
3.缺点
多层装饰较为复杂