死磕设计模式之 装饰者模式

装饰者模式

要点

  1. 类型:属于结构型设计模式
  2. 何时使用:在不想增加很多子类的情况下扩展类
  3. 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能

实现

在这里插入图片描述

代码

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:装饰者模式绕一大圈为什么不直接使用继承)

装饰器模式与继承的区别:

img

假设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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值