使用单一方法上课 -- 最佳方法?

2022-08-31 06:40:14

假设我有一个旨在执行单个函数的类。执行该功能后,可以将其销毁。有什么理由更喜欢这些方法之一吗?

// Initialize arguments in constructor
MyClass myObject = new MyClass(arg1, arg2, arg3);
myObject.myMethod();

// Pass arguments to method
MyClass myObject = new MyClass();
myObject.myMethod(arg1, arg2, arg3);

// Pass arguments to static method
MyClass.myMethod(arg1, arg2, arg3);

我故意对细节含糊不清,试图为不同情况制定指导方针。但是我真的没有想到像Math.random()这样的简单库函数。我正在考虑更多的类,这些类执行一些特定的复杂任务,但只需要一种(公共)方法来做到这一点。


答案 1

我曾经喜欢用静态方法填充的实用程序类。他们对帮助程序方法进行了很好的整合,否则这些方法会导致冗余和维护地狱。它们非常易于使用,没有实例化,没有处置,只是火不忘。我想这是我第一次在不知不觉中尝试创建面向服务的架构 - 许多无状态服务只是完成它们的工作,而没有别的。然而,随着系统的发展,龙来了。

多态
性 假设我们有一个方法UtilityClass.SomeMethod,它愉快地嗡嗡作响。突然之间,我们需要稍微改变一下功能。大多数功能是相同的,但我们仍然必须更改几个部分。如果它不是一个静态方法,我们可以创建一个派生类并根据需要更改方法内容。因为它是一种静态方法,所以我们不能。当然,如果我们只需要在旧方法之前或之后添加功能,我们可以创建一个新类并在其中调用旧类 - 但这只是粗略的。

接口问题
由于逻辑原因,静态方法无法通过接口定义。由于我们无法重写静态方法,因此当我们需要通过其接口传递静态类时,静态类是无用的。这使得我们无法将静态类用作策略模式的一部分。我们可能会通过传递委托而不是接口来修补一些问题。

测试
这基本上与上面提到的界面问题密切相关。由于我们交换实现的能力非常有限,因此在用测试代码替换生产代码时也会遇到麻烦。同样,我们可以将它们包装起来,但这需要我们更改大部分代码,以便能够接受包装器而不是实际对象。


由于静态方法通常用作实用工具方法,而实用工具方法通常具有不同的用途,因此我们很快就会得到一个装满了不一致功能的大型类 - 理想情况下,每个类都应该在系统中具有单一用途。我宁愿有五倍的课程,只要他们的目的定义明确。

参数蠕变
首先,那个可爱而无辜的静态方法可能只接受一个参数。随着功能的增长,会添加一些新参数。很快,我们又添加了可选的参数,因此我们创建了该方法的重载(或者只是在支持它们的语言中添加默认值)。不久之后,我们有一个需要10个参数的方法。只有前三个是真正必需的,参数4-7是可选的。但是,如果指定了参数 6,则还需要填写 7-9...如果我们创建一个类的唯一目的是执行此静态方法的功能,则可以通过在构造函数中采用必需的参数来解决此问题,并允许用户通过属性设置可选值,或者同时设置多个相互依赖值的方法。此外,如果一个方法已经发展到如此复杂的程度,那么它很可能无论如何都需要放在自己的类中。

无缘无故地要求使用者创建类的实例 最常见的论点之一是,为什么要求我们类的使用者创建一个实例来调用这个单一方法,而之后又没有使用该实例?
在大多数语言中,创建类的实例是非常非常便宜的操作,因此速度不是问题。向使用者添加额外的代码行对于为将来更易于维护的解决方案奠定基础是一种低成本。最后,如果你想避免创建实例,只需创建一个允许轻松重用的类的单例包装器 - 尽管这确实要求你的类是无状态的。如果它不是无状态的,您仍然可以创建处理所有内容的静态包装器方法,同时从长远来看仍然可以为您提供所有好处。最后,您还可以创建一个类来隐藏实例化,就好像它是一个单例一样:MyWrapper.Instance是一个只返回新的MyClass()的属性;

当然,只有西斯处理绝对值
,我不喜欢静态方法也有例外。不会造成任何膨胀风险的真正实用程序类是静态方法的极好案例 - 以 System.Convert 为例。如果您的项目是一次性的,不需要将来的维护,那么整体架构实际上并不是很重要 - 静态或非静态,并不重要 - 但是开发速度确实如此。

标准,标准,标准!
使用实例方法并不妨碍您同时使用静态方法,反之亦然。只要差异化背后有推理,并且它是标准化的。没有什么比查看使用不同实现方法扩展的业务层更糟糕的了。


答案 2

我更喜欢静态方式。由于 Class 不表示对象,因此创建它的实例是没有意义的。

仅针对其方法存在的类应保持静态。