装饰者模式
要点
- 类型:属于结构型设计模式
- 何时使用:在不想增加很多子类的情况下扩展类
- 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
实现
代码
Shape.java
public interface Shape {
void draw();
}
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
RedShapeDecorator.java
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");
}
}
DecoratorPatternDemo.java
public class DecoratorPatternDemo {
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());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
参照:https://www.runoob.com/design-pattern/decorator-pattern.html
个人觉得广大网友说的好的理解(ps:装饰者模式绕一大圈为什么不直接使用继承)
装饰器模式与继承的区别:
假设A为被装饰类,B与C皆为装饰器类,如果使用继承的方式扩展类的行为(如以上类图示例),有以下两个很明显的缺点;
1.组合;
先说组合,现在,B与C皆为A的装饰类,如果某一天需求说现在只需要C作为A的装饰类就可以了, 那么当前的类关系肯定是不能实现的, 所以可能就需要增加类用于继承A,提供其他的方法,或者直接修改类C,说明当前的体系扩展性很低(并且可能需要更多的冗余类来完成当前需求);
2.层次;
再说层次的问题,继承给人一种父与子的感觉,但是,现有的继承图中,这些装饰类是属于明显的层级关系,但是在现实情况中,所有装饰类应该是同一等级的,因为它们共同的目标,其实是装饰主类。
为何要用它
一个设计模式的出现一定有他特殊的价值。仅仅看见上面的结构图你可能会想,为何要兜这么一圈来实现?仅仅是想要多一行输出,我直接继承ConcretComponent,或者直接在另一个Component的实现类中实现不是一样吗?
首先,装饰器的价值在于装饰,他并不影响被装饰类本身的核心功能。在一个继承的体系中,子类通常是互斥的。比如一辆车,品牌只能要么是奥迪、要么是宝马,不可能同时属于奥迪和宝马,而品牌也是一辆车本身的重要属性特征。但当你想要给汽车喷漆,换坐垫,或者更换音响时,这些功能是互相可能兼容的,并且他们的存在不会影响车的核心属性,那就是他是一辆什么车。这时你就可以定义一个装饰器:喷了漆的车。不管他装饰的车是宝马还是奥迪,他的喷漆效果都可以实现。
再回到这个例子中,我们看到的仅仅是一个ConcreteComponent类。在复杂的大型项目中,同一级下的兄弟类通常有很多。当你有五个甚至十个ConcreteComponent时,再想要为每个类都加上“ready?go!”的效果,就要写出五个子类了。毫无疑问这是不合理的。装饰器模式在不影响各个ConcreteComponent核心价值的同时,添加了他特有的装饰效果,具备非常好的通用性,这也是他存在的最大价值。
参考文章:
https://www.cnblogs.com/jzb-blog/p/6717349.html
https://www.runoob.com/design-pattern/decorator-pattern.html