什么时候应该使用公共静态方法
Posted
技术标签:
【中文标题】什么时候应该使用公共静态方法【英文标题】:When should you use public static methods 【发布时间】:2011-03-23 06:13:42 【问题描述】:有很多人反对使用“公共/私有”静态方法。我四处寻找,没有运气,并试图找到任何提倡善用静态方法的人。
假设方法始终是内聚的,在哪里可以使用公共静态方法?这些方法在 Java 和 .NET 之间是否有所不同(也就是在一种方法中比另一种更容易接受)?
最近的 SO 帖子激起了我对这个话题的愤怒/兴趣。
【问题讨论】:
您发布此问题时要寻找的答案是什么? 类似于 Michael Borgwardt 的回答,我只是在等着看是否有人对它是否有任何想法,如果它在 b/w Java 和 .NET 上有所不同。 【参考方案1】:如果方法可以被视为一个单元,并且可以单独进行有效测试,则使用公共静态方法。在使用静态方法的类型上实现依赖注入或模拟是很困难的。
我为实用程序方法使用静态方法,几乎没有/没有依赖关系,以及定义明确的输入/输出。
【讨论】:
为什么在使用静态方法的类型上很难使用 DI?同意您是否在谈论模拟具有静态方法的类... @Nix:请原谅我偏离了语言不可知论者一点。在 .NET 中,静态方法不能是接口的成员。这减少了模拟对象时可用的选项,因为 .NET 仅支持类的单一继承,并且接口不描述整个类契约。请注意,使用 DI with 静态方法仍然是同样的故事,只是很难使用 DI with 静态方法。【参考方案2】:静态方法一般不应该:
访问其参数之外的任何状态(因为这会导致难以更改的耦合) 修改它的参数(因为如果有,为什么不是那个参数的实例方法?)相反,纯函数(即没有副作用)是好的静态方法。
当然,这不应该被视为绝对的教条。
【讨论】:
Singleton GetInstance,是修改静态的静态方法最好的例子(可以初始化单例对象) @Nix:单身人士通常被认为不是一件好事。在访问器中初始化它们主要用于产生关于双重检查锁定的无休止的毫无意义的讨论。【参考方案3】:我会说在简单的工厂中使用它们是公平的,比如返回包含静态方法的类型的场景。如果:
string.Empty;
是一个合法的静态属性 那么:
string.GenerateRandomString();
是合法的静态方法。不过即便如此,我也可以看到纯 OO 程序员可能更喜欢 StringFactory 或 RandomStringGenerator 类,但我想这完全取决于你在哪里画线。
【讨论】:
我对过度设计提出异议,我担心的是不要使用静态方法!将不必要地增加代码复杂性。在我们的领域中,所有关于理解何时需要“StringFactory”或“RandomStringGenerator”。 @Nix:我同意。静态方法有它们的位置。在我的应用程序中,它们倾向于用于实用程序类。【参考方案4】:将方法标记为静态告诉消费者您不会更改传递给该方法的任何对象的状态。静态方法应该对其传递的参数执行操作,并且不应该依赖任何内部字段。
我相信您参考的帖子中给出的具体建议与静态方法所在的位置有关 - 而不是反对使用静态方法的建议。
【讨论】:
在我看来,帖子所指的文章说不要使用静态方法......让它们成为方法,因为静态方法缺乏凝聚力。静态类只能*依赖内部静态字段*并且修改它们没有错...?为什么静态方法不能更改传递给它们的对象? (假设是故意的)【参考方案5】:一个典型的用途是实现单例模式。
【讨论】:
没错,但我们中的一些人认为 Singleton 很少适合。例如见c2.com/cgi/wiki?SingletonsAreEvil 像任何其他工具一样,如果使用得当,Singleton 是好的。导致问题的是“正确使用”的部分,人们很少正确使用它。【参考方案6】:我将静态/共享用于不属于类实例的方法,或者如果我正在更新“共享”变量(请记住使它们成为线程安全的)。
通常,这意味着我最终将这些方法放在包含它们的不同“管理器”类中,我还将构造函数标记为私有以确保它们无法实现。
附带说明:静态/共享方法是slightly faster,我记得它们在 CLR 中的实现与 OOP 无关,并且不允许在与 OOP 语言(. NET 至少)Java 固有的 - Discussed Here。
【讨论】:
【参考方案7】:静态方法与全局对象实例上的实例方法具有相同的语义。除非您对全局对象实例很熟悉,否则您不应该使用静态方法。也就是说,这在很大程度上取决于情况。有时,一个讨厌的黑客是正确的做法。
【讨论】:
以上是关于什么时候应该使用公共静态方法的主要内容,如果未能解决你的问题,请参考以下文章