假设我有一个用于执行单个功能的类.执行该功能后,可以将其销毁.有没有理由更喜欢这些方法之一?
// 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()这样的简单库函数.我正在考虑更多执行某些特定复杂任务的类,但只需要一个(公共)方法来执行它.
我曾经喜欢充满静态方法的实用工具类.他们对辅助方法进行了很好的整合,否则会导致冗余和维护.它们非常容易使用,没有实例化,没有处置,只是火不会忘记.我想这是我第一次不知不觉地尝试创建面向服务的体系结构 - 许多无状态服务只是完成了自己的工作而没有其他工作.然而,随着系统的发展,龙将会到来.
多态性
假设我们有方法UtilityClass.SomeMethod愉快地嗡嗡作响.突然间我们需要稍微改变功能.大多数功能都是相同的,但我们必须改变几个部分.如果它不是静态方法,我们可以创建一个派生类并根据需要更改方法内容.因为它是一种静态方法,我们不能.当然,如果我们只需要在旧方法之前或之后添加功能,我们可以创建一个新类并在其中调用旧类 - 但这只是粗略的.
接口问题
出于逻辑原因,无法通过接口定义静态方法.由于我们无法覆盖静态方法,因此当我们需要通过接口传递静态类时,静态类是无用的.这使我们无法使用静态类作为策略模式的一部分.我们可能通过传递代理而不是接口来修补一些问题.
测试
这基本上与上面提到的界面问题密切相关.由于我们交换实现的能力非常有限,我们也很难用测试代码替换生产代码.同样,我们可以将它们包装起来,但它需要我们更改代码的大部分内容,以便能够接受包装而不是实际的对象.
Fosters blob
由于静态方法通常用作实用方法,而实用方法通常会有不同的用途,我们很快会最终得到一个充满非连贯功能的大类 - 理想情况下,每个类在系统中都应该有一个目的.只要他们的目的很明确,我宁愿拥有五次课程.
参数蠕变
首先,这个小巧可爱且无辜的静态方法可能需要一个参数.随着功能的增长,添加了几个新参数.很快又添加了可选的参数,因此我们创建了方法的重载(或者只是在支持它们的语言中添加默认值).不久,我们有一个方法,需要10个参数.实际上只需要前三个,参数4-7是可选的.但是如果指定参数6,则需要填写7-9 ...如果我们创建了一个具有执行此静态方法的单一目的的类,我们可以通过接受所需的参数来解决这个问题.构造函数,并允许用户通过属性或方法设置可选值,以同时设置多个相互依赖的值.此外,如果一种方法已经增长到这种复杂程度,
要求消费者无缘无故地创建类的实例
最常见的一个论点是,为什么要求我们类的使用者创建一个用于调用这个方法的实例,而之后却没有使用该实例?在大多数语言中创建类的实例是非常便宜的操作,因此速度不是问题.向消费者添加额外的代码行是为将来构建更易维护的解决方案奠定基础的低成本.最后,如果你想避免创建实例,只需创建一个类的单例包装器,以便于重用 - 尽管这确实要求你的类是无状态的.如果它不是无状态的,你仍然可以创建处理所有内容的静态包装方法,同时从长远来看仍然可以带来所有好处.最后,
只有西斯处理绝对值
当然,我不喜欢静态方法.对静态方法没有任何风险的真实实用程序类是静态方法的优秀案例 - 以System.Convert为例.如果您的项目是一次性的,对未来的维护没有要求,那么整体架构确实不是很重要 - 静态或非静态,并不重要 - 然而,开发速度确实如此.
标准,标准,标准!
使用实例方法不会阻止您使用静态方法,反之亦然.只要有分化背后的推理并且它是标准化的.没有什么比查看具有不同实现方法的业务层更糟糕的了.
我更喜欢静态方式.由于Class不表示对象,因此创建它的实例没有意义.
仅存在于其方法中的类应保持静态.
如果没有理由为了执行该函数而创建类的实例,那么使用静态实现.为什么让这个类的使用者在不需要时创建一个实例.
如果您不需要保存对象的状态,则无需首先实例化它.我将使用您传递参数的单一静态方法.
我还要警告一个巨大的Utils类,它有许多不相关的静态方法.这可能会匆忙地变得杂乱无章.最好有很多类,每个类都有很少的相关方法.
我会说静态方法格式是更好的选择.而且我也会使类静态化,这样你就不必担心意外地创建类的实例.
我真的不知道这里的情况是什么,但我会把它作为一个方法放在arg1,arg2或arg3所属的类中 - 如果你可以在语义上说其中一个类拥有方法.