【问题标题】:Java Abstract Class or Static Utility Class Design ChoiceJava 抽象类或静态实用程序类设计选择
【发布时间】:2010-07-26 15:19:24
【问题描述】:

我正在实施一些策略(Strategy Pattern),它们有一些共同的行为,但我不确定共同操作应该放在哪里。

  • 假设我有 1 个上下文和 3 个策略,策略中使用的一些操作是共享的,一些只需要 2 个其他的只是策略之一。
  • 没有共享成员级别的状态,因此唯一的操作实际上是无状态的。
  • 这些操作的目的是支持将状态格式化为文件,例如视图助手。

选项 1:创建一个 AbstractStrategy 类

  • 我正在使用 Java,所以这立即 带走在 未来。
  • 往往会产生继承。 在山脊结构中。
  • 操作将是最终的。

选项 2:创建静态帮助器的 Util 类

  • 灵活,但不知为何感觉像是代码异味。
  • 没有脊。

有什么建议或偏好吗?

请注意,我工作的级别是策略级别,而不是上下文级别(请参阅维基百科链接)。

【问题讨论】:

  • 当需要遵循 open-close 模式时,我更喜欢使用抽象,即程序将对扩展开放但对修改关闭...

标签: java design-patterns oop


【解决方案1】:

有一个原因...一个巨大原因...在抽象类或接口上使用静态 Util 类。

因此您可以在以后添加更多方法。

对于抽象类或接口,您对该类/接口所做的任何更改都必须在从它继承的所有类中进行更改。如果您正在编写公共 API,这尤其成问题。

Java 框架具有散布在各处的带有静态方法的实用程序类。最著名的是java.util 包:CollectionsArrays

【讨论】:

  • 好点。我个人认为静态是要走的路。这些函数非常适合 ViewHelper 模式,因此过于复杂化似乎没有必要。
  • 在这个主题上,我认为 RestAssured 库和 XMLSlurper(在 Groovy 项目中)都是使用静态实用程序类的好例子。
【解决方案2】:

有很多方法可以实现这一点。

  1. 使用抽象类,将执行的可变部分变成抽象方法 => 一些策略将实现所有操作(通过覆盖抽象方法),而其他策略则可以跳过可选操作。 请注意,在这种情况下,可选操作可能是空钩子方法而不是抽象方法。这样就避免了将这些操作作为子类中的空方法实现的麻烦。

  2. 使用实际的“策略”界面(使用您指向的维基百科文章中的执行方法)。然后,客户端类将由策略的实现提供(可以是匿名内部类或实际成熟的策略类)。

第一个更直接但更严格:如果您必须修改操作的数量(特别是抽象操作),则必须更新所有子类。

第二个更灵活,但您必须找到一种方法,通过委托或使用静态实用程序方法在不同策略之间“共享”通用操作。

【讨论】:

  • “第二个更灵活,但您必须找到一种方法,通过委托或使用静态实用程序方法在不同策略之间“共享”通用操作。” -- 战略是我工作的水平,而你所说的“共同部分”是我要解决的问题。
  • 公用部分是否适合小型企业?我的意思是:它们可以被建模为函数吗?如果是这样,我建议将这些操作封装在小的“操作”类中并重用这些跨策略。在这种情况下,优点是可测试性和可重用性。
  • 小单位是的,但不是整个企业。仅适用于策略 - 所以我认为静态 util 包受到限制,想法?
  • 如果您只需要无状态逻辑,那么封装受限的静态方法与对象一样好。你失去了多态性(以及 OO 纯粹主义者的喜爱和支持 ;-),但它仍然是可测试和可重用的。
【解决方案3】:

除了您列出的两个选项之外,还有另一个选项:

在我看来,你想要某种组合,你可以只提取你需要的功能。也许您可以使用命令模式打包您的操作,然后从中组装您的策略?

优点:

  • 不需要策略继承。
  • 策略将无法看到未使用/隐藏的“共享方法”。
  • 没有包含一堆(可能)不相关的方法的静态实用程序类。
  • 单元测试更简单 - 可以单独测试操作。
  • 迭代操作的简单共享策略类。

缺点:

  • 其他类。
  • 操作必须符合可能有限制的通用命令界面。
  • 对于非常简单的操作可能会过度杀伤力 - 您的格式化程序可能就是这样。

【讨论】:

  • 在这种情况下,策略与命令非常相似,所以我看不出如何避免继承,因为如果我理解正确,命令仍然需要在它们之间共享通用功能,你如何建议那要实施吗?
  • 我建议策略由命令组成。每个“函数”都是一个命令实例。然后,您可以通过选择适当的命令来简单地制定策略。
【解决方案4】:

如果它被声明为Abstract,人们可能会猜测它是为扩展而设计的。 所以声明一个私有构造函数是一个更好的主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2012-12-03
    • 2012-08-07
    • 2017-04-05
    • 2012-10-01
    • 2011-06-21
    • 1970-01-01
    相关资源
    最近更新 更多