繁体   English   中英

替代 static 使用 Java 中的类和方法

[英]Alternative to static Util Classes and Methods in Java

说,我想要这个方法,它需要一个 Set 并根据某种逻辑将其格式化为一个字符串。 例如。

public String formatCustomerSet(final Set<Customer> customers) {
    String result = "";
    for (Customer customer : customers) {
        result += customer.getFirstName() + " : " + customer.getLastName() + "\n";
    }

    return result;
}

我在几个类中使用此代码。 现在,我应该把这个放在哪里? 我发现应该避免使用实用程序类,不应该使用? https://lostechies.com/chrismissal/2009/06/01/anti-patterns-and-worst-practices-utils-class/

那么,它应该是使用特定名称的 Util class (例如使用的 CustomerFormatter)还是我们应该使用 OOP class ? 推荐哪一个,为什么?

我在几个类中使用此代码。 现在,我应该把这个放在哪里? 我发现应该避免使用实用程序类,不应该使用? https://lostechies.com/chrismissal/2009/06/01/anti-patterns-and-worst-practices-utils-class/

那么,它应该是使用特定名称的 Util class (例如使用的 CustomerFormatter)还是我们应该使用 OOP class ? 推荐哪一个,为什么?

使用 Java 流,您实际上可以通过以下单行获得所需的内容(假设Customer类中有一个好的toString() ):

String result = 
    customers.stream().map(Customer::toString).collect(Collectors.joining("\n"));

放置它的一个好地方可能是Customer class 本身。 但我会开始使用它,只有在收集了一些有关用例的信息后,我才会考虑将其重构为独立的 class。

编辑(对评论的回答) :是的,我首先在Customer class 中将此方法设为 static 方法,因为它确实不使用该 class 中的任何字段。

编辑 2(注):顺便说一下,如果您想在问题中使用该方法,请考虑使用StringBuilder而不是String

我不同意应避免使用 util 类的事实。 拥有一个包含纯实用程序的 static 方法的 class 是非常好的。 有时函数或操作应该只是函数或操作。 并不总是需要将它们与一些抽象的 object 类型或其他类型相关联。

但是,我同意的是,在制作实用程序类时,您应该严格定义 class 将提供哪些类型的实用程序。 如果您有一堆与进行数学运算相关的 static 方法,您可以制作一个 util class ExtendedMath 如果您正在做大量的数学运算并且 class 变得太胖,请尝试进一步完善它。 按数学类型(例如AlgebraVector )对它们进行分组。

最后,它大多只是试图使用常识。 function 成为 object 的一部分是否有意义,或者它只是一个任意操作?

在您的情况下,您必须问自己一个问题:“我想创建我的代码对formatCustomerSet实现的硬依赖吗?”。 如果您 100% 确定您将始终以完全相同的方式格式化客户集,并且您永远不需要不同的格式化程序,那么使用 static 方法可能没问题。 如果没有,那么最好将其作为非静态 function 放在CustomerSetFormatter class 上。

我不能给你一个是或不是的答案,因为你必须自己权衡利弊。 只需考虑以下事项:

  • 当您引用 static 方法时,您正在创建对该 static 方法的硬依赖 有时这没关系,有时则不然。 软件开发的一个核心原则是重用 您能否在其他上下文中重用调用 static function 的代码? 或者 static function 是否过于特定于上下文?
  • 编程中的另一个核心原则是依赖注入 假设您有需要客户格式化程序的Class A 你可以做的是,你可以制作一个interface CustomerFormatter 然后在Class A定义一个构造函数: A(CustomerFormatter formatter) 这允许您做的是在使用不同的CustomerFormatter实现时重用Class A 这大大增加了Class A的可重用性。 当使用 static 函数时,这不再可能。
  • 常见的通用运算(例如Math中定义的函数,例如min()max()ceil()floor() )完全保证是 static 函数。 他们做一件常用的事,而且只做一件事。 通常,您可以将这样的功能作为 static 方法完全保证的示例。
  • 您的 function 是纯 function吗? 这是一个 function,对于任何唯一输入,它总是给出完全相同的 output。 如果输入保持不变,对相同函数的后续调用将始终产生相同的结果。 如果是这种情况,那么制作您的方法 static 就可以了。 如果不是这种情况,并且随后对同一 function 的调用会根据某些仲裁 state 或之前完成的调用给出不同的输出,那么您应该考虑使其成为非静态的。 使 static 函数为相同的输入提供不同的输出,因为它们依赖于一些 state,通常被视为一种反模式

我希望这对你有所帮助。

在大多数情况下,最好将行为作为非静态方法直接添加到已经存在的类中。 如果您真的想重用它,最好创建一个具有所需行为的新 class 但作为常规 class,它需要被实例化并且可以被子类化。

实用程序/静态类的缺点:主要问题是 class 取决于来自实用程序 Class 的 static 方法具有紧密耦合

  1. 测试有点困难:由于您对 Util Class 有很强的依赖关系,因此您无法轻松提供模拟实现。
  2. 控制反转:使用实用程序类时无法进行依赖注入。
  3. 代理:许多框架依赖于动态代理来向 class 实例添加附加功能,例如日志级别,这对于实用程序类是不可能的。
  4. 单一职责:随着时间的推移,如果你不是很严格,这些类往往会积累越来越多的代码,这可能与原始方法没有太大关系。 class 将失去其最初的单一职责。

参考: https://www.vojtechruzicka.com/avoid-utility-classes/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM