有了域名怎么建网站联系方式,网站建设站长,企业营销策划推广,小程序代理平台设计模式装饰者模式在工作中#xff0c;我正在处理庞大的Java代码库#xff0c;该代码库是由许多不同的开发人员在15年的时间里开发的。 并不是所有的事情都由书来完成#xff0c;但是同时我通常无法重构遇到的每一个奇怪的事物。 尽管如此#xff0c;仍可以每天采取提高代… 设计模式装饰者模式 在工作中我正在处理庞大的Java代码库该代码库是由许多不同的开发人员在15年的时间里开发的。 并不是所有的事情都由书来完成但是同时我通常无法重构遇到的每一个奇怪的事物。 尽管如此仍可以每天采取提高代码质量的措施。 今天就像那样…… 总览 由于已 存在 大量 教程 因此本文的目的不是教授装饰器模式。 相反它提供了一个现实生活中的示例说明它如何派上用场并节省了一天的时间。 情况 我们的UI包含Swing的JEditorPanes 用于显示HTML。 与各种链接如悬停和单击的交互会触发以下一个或多个响应 记录事件 更改光标JEditorPane已经自行完成似乎从2000年5月开始-… 使用链接的内容更新窗格 打开外部浏览器 打开外部应用程序 处理内部服务请求 对于所有窗格这些响应都不相同。 其中有一些需求部分不同。 如果您知道装饰器模式那么您会看到它的去向。 所以问题是您如何实施这些响应 一种可配置类的解决方案 您可以将所有这些都放在一个类中该类实现HyperlinkListener并使用标记来取消激活不同的响应。 这个课真是地狱 是的地狱 就这么简单。 首先它将是巨大的。 而且其本质上不相关的职责之间可能以某种方式有些奇怪的依赖。这种规模和这些关系将使编写和测试变得更加困难甚至使理解和修改变得更加困难。 顺便说一句造成混乱的根本原因是AllInOneHyperlinkListener违反了单一责任原则 。由于这篇文章已经足够长了因此我将不作详细介绍。 继承的解决方案 无论如何我很幸运没有发现自己正在面对一个庞然大物的听众。 取而代之的是我发现了一个小的类层次结构这些类将这些职责划分为它们 HL是HyperlinkListener的缩写 CursorSettingHL implements HL 记录事件并设置光标 UrlProcessingHL extends CursorSettingHL 通过更新窗格的内容或打开外部浏览器/应用程序来处理URL ServiceRequestHandlingHL extends UrlProcessingHL 如果是服务请求则处理URL 否则委托给它的超类 这看起来更好不是吗 好… 首先某些班级仍然要承担几项责任。 没有真正的理由解释为什么日志和更改游标应该由同一类完成。 我只能猜测这种结构会随着时间的推移而有机地增长而没有任何更深层次的设计。因此问题较小但尚未消失。 它也显示在班级名称中。 上面的内容已经过改进以提高可读性。 原始文档中充满了Default Simple和其他非信息。 这个名字甚至是误导性的名字都不是简单的疏忽。 它们是缺乏凝聚力的自然结果。 但是通过更深层次的管理这些问题本来可以得到缓解。 六个类可以各自实现一件事。 但这也不会帮助我。 不此解决方案的真正问题是模拟的灵活性。 看起来您可以选择但实际上您不能。 看看当事情改变时会发生什么。 改变 我们慢慢地从摇摆移动到JavaFX的我想以取代FX JEditorPane中” 的WebView 。 实际上将HyperlinkListeners放入WebView有点麻烦但我将在另一篇文章中再讨论。WebView已经完成了上面的某些操作因此这是新侦听器具有的更新响应列表。触发 记录事件 改变光标 用新内容更新窗格 打开外部浏览器 打开外部应用程序 处理内部服务请求 在这里整个类系统变得毫无用处。 至少因为我不愿意让监听者对隐身控件进行2.和3.。在这一点上很明显职责混在一起了。 我仍然需要其中一些但不是全部而且由于它们之间没有阶级界限所以我处于全有或全无的情况。 救援人员的装饰模式 因此当我在考虑要混合和匹配现有功能的程度时它最终使我感到痛苦并且比预期的要晚得多这正是装饰器模式的目的 装饰图案 就像我说的我不会详细介绍这种模式但是基本思想是 当存在一个接口不同的实现可以提供不同的功能时请让每个实现独立运行。 但是要实现它们以便在工作中的某个时刻他们将控制权移交给同一接口的另一个实例。 如果一个这样的实现调用另一个并使用该结果来计算自己的实现那么两者都会做自己的事情但是效果会重叠。 第二个实例的结果仍然存在但第一个实例有些改变。 因此据说第一个装饰第二个。 这可以在更多实例中进行每个实例都装饰前者。 应该将其视为分层系统其中每个装饰器向整体添加另一层行为。 行动中 现在方法很清楚我将上述功能重构为不同的装饰器例如LoggingHyperlinkListenerDecorator和ServiceRequestHandlingHyperlinkListenerDecorator 。 然后我删除了原始类并用正确的装饰器组合替换了它们的用途。 最终我了解了新功能并选择了正确的装饰器。 用Java 8可以做到这一点但是为了简单起见让我们在这里使用构造函数 将装饰器放在一起 // use a lambda expression to create the initial listener
// which does nothing
HyperlinkListener listener event - {};
// these decorators first do their own thing and then call the
// decorated listener (the one handed over during construction);
// in the end, the last added decorator will act first
listener new ExternalApplicationOpeningHyperlinkListenerDecorator(listener);
listener new BrowserOpeningHyperlinkListenerDecorator(listener);
listener new ServiceRequestHandlingHyperlinkListenerDecorator(listener);
listener new LoggingHyperlinkListenerDecorator(listener); 除了样板之外很明显这里发生了什么。 首先在我们确定服务请求并处理它们之前将进行日志记录。 如果可能将在浏览器中打开其他任何内容 否则我们会将其交给一些外部应用程序。 效果 您马上就可以看到对代码的积极影响。 首先每个班级都有一个非常简单的责任。 这导致了简短易懂的课程。 他们的名字通常是当场就正确地告诉您他们在做什么。 另外由于每个单元中发生的事情较少因此可测试性也提高了。 此外将装饰器放在一起的地方更能揭示其意图。 您不必检查实例化的ServiceRequestHandlingHyperlinkListener及其超类即可了解侦听器的确切功能。 取而代之的是您仅查看装饰列表看看会发生什么。 最后但并非最不重要的一点它使代码为将来的更改做好了准备。 现在很明显如何实现新的侦听器功能。 对于继承的类您必须想知道在何处放置新功能以及新功能如何影响该类的现有用法。 现在您只需实现第updecth装饰器并在需要的地方添加它即可。 反射 这个真实的例子展示了装饰器模式的应用如何使代码更易于阅读测试和更改。 当然这不是自动的。 该模式只能在确实使代码更清洁的地方使用。 但是要决定这一点您必须了解它并且必须能够推理其影响。 我希望这篇文章对此有所帮助。 非常感谢Wikipedia的Benjah 他创造了 Vaska复杂建筑 的美丽形象并将其发布到公共领域。 翻译自: https://www.javacodegeeks.com/2015/01/how-the-decorator-pattern-saved-my-day.html设计模式装饰者模式