我在前面的堆栈溢出回答中写了我对静态类的想法:单方法类-最佳方法?
我以前喜欢用静态方法填充的实用程序类。他们对助手方法进行了很好的整合,否则会导致冗余和维护混乱。他们非常容易使用,没有实例化,没有处理,只是火‘不’忘记。我想这是我第一次无意中尝试创建一个面向服务的体系结构-许多无状态服务只是完成了他们的工作,而没有其他任何东西。然而,随着一个系统的发展,龙就要来了。
多态
假设我们有UtilityClass的方法。突然,我们需要稍微改变一下功能。大多数功能是相同的,但我们仍然需要更改几个部分。如果不是静态方法,我们可以创建一个派生类并根据需要更改方法内容。当然,如果我们只需要在旧方法之前或之后添加功能,我们就可以创建一个新类,并在其中调用旧类-但这太糟糕了。
界面问题
由于逻辑原因,不能通过接口定义静态方法。由于我们不能覆盖静态方法,所以当我们需要通过它们的接口传递它们时,静态类是无用的。这使我们无法使用静态类作为策略模式的一部分。我们可以通过传递委托而不是接口.
测试
这基本上与上面提到的界面问题密切相关。由于我们交换实现的能力非常有限,我们在用测试代码替换生产代码时也会遇到困难。同样,我们可以将它们封装起来,但这将要求我们修改代码的大部分,以便能够接受包装器而不是实际的对象。
胎圈
由于静态方法通常被用作实用方法,实用方法通常有不同的用途,所以我们很快就会得到一个包含非一致性功能的大类-理想情况下,每个类在系统中应该有一个单一的用途。我宁愿有五倍的课程,只要他们的目的是明确的。
参数蠕变
首先,这个可爱而又天真的静态方法可能只需要一个参数。随着功能的增加,添加了几个新的参数。不久,会添加更多的参数,这些参数是可选的,因此我们创建了方法的重载(或者只是在支持它们的语言中添加默认值)。不久,我们就有了一个采用10个参数的方法。只有前三个是真正需要的,参数4-7是可选的。但如果指定了参数6,也需要填写7-9.如果我们创建一个类的唯一目的是做这个静态方法所做的事情,我们就可以通过在构造函数中接受所需的参数来解决这个问题,并允许用户通过属性设置可选值,或者同时设置多个相互依赖的值的方法。而且,如果一个方法已经发展到如此复杂的程度,那么它很可能需要在它自己的类中。
要求使用者无缘无故地创建类的实例。
最常见的论点之一是:为什么要求我们类的使用者创建一个实例来调用这个单一的方法,而之后却不使用这个实例?在大多数语言中,创建类的实例是非常廉价的操作,因此速度不是问题。向使用者添加额外的代码行对于将来为更易于维护的解决方案奠定基础来说是一项低成本的工作。最后,如果您想避免创建实例,只需为您的类创建一个允许容易重用的单例包装器-尽管这确实使您的类成为无状态的要求。如果它不是无状态的,则仍然可以创建处理一切的静态包装器方法,同时也可以为您提供长期的所有好处。最后,您还可以创建一个类来隐藏实例化,就好像它是一个单例:MyWrapper.Instance是一个只返回的属性new MyClass();
只有西斯的交易才是绝对的。
当然,我不喜欢静态方法也有例外。对于静态方法来说,不存在任何膨胀风险的真正实用程序类是很好的例子-System.Convert作为一个例子。如果您的项目是一次性的,不需要将来的维护,那么总体架构确实不是非常重要的-静态的或非静态的,并不是真正重要的-但是,开发速度确实很重要。
标准,标准!
使用实例方法并不妨碍您也使用静态方法,反之亦然。只要有理由背后的差别和它是标准化的。没有什么比查看具有不同实现方法的业务层更糟糕的了。