使用单一方法的类 - 最佳方法?

问题

假设我有一个用于执行单个功能的类。执行该功能后,可以将其销毁。有没有理由更喜欢这些方法之一?

// 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 热门回答(235 赞)

我曾经喜欢充满静态方法的实用工具类。他们对辅助方法进行了很好的整合,否则会导致冗余和维护。它们非常易于使用,没有实例化,没有处理,只是火不会忘记。我想这是我第一次不知不觉地尝试创建面向服务的体系结构 - 许多无状态服务只是完成了自己的工作而没有其他工作。然而,随着系统的发展,龙将会到来。

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

接口问题
由于逻辑原因,无法通过接口定义静态方法。由于我们无法覆盖静态方法,因此当我们需要通过接口传递静态类时,静态类是无用的。这使我们无法使用静态类作为策略模式的一部分。我们可能会通过passing delegates instead of interfaces修补一些问题。

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

Fosters blobs
由于静态方法通常用作实用方法,而实用方法通常会有不同的用途,我们很快就会得到一个充满非连贯功能的大类 - 理想情况下,每个类在系统中都应该有一个目的。只要他们的目的明确定义,我宁愿拥有五次课程。

参数creep
首先,这个小巧可爱且无辜的静态方法可能只需要一个参数。随着功能的增长,添加了几个新参数。很快又添加了可选的参数,因此我们创建了方法的重载(或者只是在支持它们的语言中添加默认值)。不久,我们有一个方法,需要10个参数。实际上只需要前三个,参数4-7是可选的。但是如果指定参数6,则需要填写7-9 ...如果我们创建了一个具有执行此静态方法所做的单一目的的类,我们可以通过获取所需的参数来解决这个问题。构造函数,并允许用户通过属性或方法设置可选值,以同时设置多个相互依赖的值。此外,如果一种方法已经发展到这种复杂程度,那么它很可能无论如何都需要在自己的类中。

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

只有一个西斯交易绝对数
当然,我不喜欢静态方法。真正的实用程序类对膨胀没有任何风险是静态方法的优秀案例 - 以System.Convert为例。如果你的项目是一次性的,对未来的维护没有要求,那么整体架构确实不是很重要 - 静态或非静态,并不重要 - 但开发速度确实如此。

标准,标准,标准!
使用实例方法不会阻止你使用静态方法,反之亦然。只要有差异化背后的推理,它就是标准化的。没有什么比查看具有不同实现方法的业务层更糟糕的了。


#2 热门回答(79 赞)

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

仅存在于其方法中的类应保持静态。


#3 热门回答(15 赞)

如果没有理由为了执行该函数而创建类的实例,那么使用静态实现。为什么要让此类的使用者在不需要时创建实例。