装饰模式

本贴最后更新于 2492 天前,其中的信息可能已经东海扬尘

前言

最近在梳理 IO 相关知识。众所周知,装饰模式大量运用在 Java 流的体系设计中。今天就简单的回顾下装饰模式的相关概念。

简介

设计模式 中,装饰模式属于结构型模式,也就是说用来处理对象之间的关系。在面向对象程序设计中,处理对象间关系基本的手段包括 继承,和 组合。装饰模式就是典型的利用组合来达到对象关系处理和代码复用的目的。

一个简单的例子

现在有一个抽象的 Person 类,需要设计出具有不同走路方式的 Person 实现类。很容易给出以下继承实现的解决方案:

屏幕快照 2018-01-07 下午 11.07.22.png

每个具体人类的 run 方法中都调用了自己特有的方法比如 smile,talk 等。

在上面继承方案中有两个明显的问题:

  1. 代码没有得到很好的复用,比如 Laura 想要 smiletalk,除了自己声明其中一个方法,另一个继承。是没有办法多继承的。在 Java 中不允许多继承。
  2. 类的数量会越来越多。比如,要表示每个人所有可能行为的集合。这里有 4 个人定义了 3 种行为,最坏情况则需要 28 个类。

这就是继承无法解决的问题,那么这个时候可以使用组合的方式来达到同样的目的,并且避免上面的问题。看下装饰模式的解决方案:

屏幕快照 2018-01-07 下午 11.51.53.png

在装饰模式中可以看到另一个实现了 Person 接口的分支。这是关键。RunBehaviour 是一个抽象类,最为重要的是它持有了一个 Person 类型的引用,并且有一个接受 Person 类型的构造函数。RunBehaviour 称之为装饰器,它的子类则是具体的 装饰器。那些直接实现了 Person 接口的类则称之为具体的 构件类。由于具体装饰器类和构件类实现了同样的接口。那么装饰器类就可以通过持有构件类使用自己特有的方法来对构建类进行增强,同时对外提供相同的接口。使用的时候就像使用原来构件类一样!

客户端代码

Person person1,person2;

person1 = new Tom();

person2 = new Talk(person1);

person2.run();

这样 Tom 就可以在 run 的时候 talk 了。并且可以继续通过这种方式为 Tom 增加更多的行为。

透明和半透明装饰模式

透明

像上面这种方式。我们要对构件类的原有方法进行增强。那么对于装饰过的类并没有特有的方法。一切的使用和接口里约定的一样,只不过方法被 装饰 了。客户端使用起来和原来构建类一样,感觉不到区别。

半透明

有的时候我们需要单独调用装饰类中新增的方法,而不是在原有接口方法中调用。这个时候把装饰类声明为父类型,就会丢失访问特有方法的能力。那么只能把它声明为具体装饰类型。这个时候客户端就要关心这个区别了,所以称之为半透明。

优缺点

  • 优点:装饰模式很好的利用对象的组合来为对象增加职责,同时构件的变化和装饰器的变化互不影响。符合 开闭原则
  • 缺点:对一个对象进行装饰的时候,会产生大量装饰类,增加使用复杂性。这也是 Java IO 令人疑惑的地方之一
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • 装饰
    1 引用

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...