一般认为过度依赖全局变量是应该避免的。那使用静态类和方法是否等同呢?
一般认为过度依赖全局变量是应该避免的。那使用静态类和方法是否等同呢?
全局数据是不好的。但通过使用静态方法可以避免许多问题。
我借鉴了Rich Hickey的观点来解释这个问题:
在C#中,为了构建最可靠的系统,请使用静态方法和类,而不是全局数据。例如,如果您将数据对象传递给静态方法,并且该静态方法不访问任何静态数据,则可以确信,针对给定输入数据,该函数的输出始终相同。这是Erlang、Lisp、Clojure和每个其他函数式编程语言所采取的立场。
使用静态方法可以大大简化多线程编程,因为,如果正确编程,只有一个线程将同时访问给定数据集。这就是关键所在。全局数据很糟糕,因为它是可以被不知道哪个线程何时更改的状态。然而,静态方法允许非常干净的代码,可以按较小的增量测试。
我知道这可能会引起激烈争论,因为它与C#的面向对象思想背道而驰,但我发现使用越来越多的静态方法,我的代码越来越清晰、可靠。
这个视频比我更好地解释了这一点,但它展示了不可变数据和静态方法如何产生极其线程安全的代码。
让我更明确一些关于全局数据的问题。常量(或只读)全局数据比可变(读/写)全局数据不那么重要。因此,如果有意义拥有全局缓存数据,则使用全局数据!在某种程度上,使用数据库的每个应用程序都将具有这种情况,因为我们可以说所有SQL数据库都是一个大型的全局变量,保存数据。
因此,像我上面所说的那样做出一个笼统的陈述可能有点过分。相反,我们可以说,使用全局数据会引入许多问题,而使用本地数据则可以避免这些问题。
一些编程语言,如 Erlang,通过在单独的线程中缓存处理所有对该数据的请求来解决这个问题。这样,您就可以知道对该数据的所有请求和修改都是原子的,全局缓存也不会处于某种未知状态。
static
并不一定意味着全局的。类和成员可以是static private
,因此仅适用于特定的类。也就是说,过多使用public static
成员而不是使用适当的方式传递数据(方法调用、回调等)通常是不良的设计。
static private
数据仍然是全局的,尽管它只对相关类可见。 - Jeff Sternal如果您试图在面向对象的开发中保持纯粹主义,那么静态方法可能并不适合这种模式。
然而,现实世界比理论更加混乱,静态方法通常是解决某些开发问题的非常有用的方式。适当使用,并适度使用。
除了其他所说的,final static
变量是可以的;常量是好的。唯一的例外是当你应该将它们移到属性文件中以方便更改。
public class Foo
{
private static int counter = 0;
public static int getCounterValue()
{
return counter;
}
//...
public Foo()
{
//other tasks
counter++;
}
}
我认为全局变量的不好之处在于引入了全局状态的概念 - 变量可以在任何地方被操作,并且往往会在程序的远程区域引起意想不到的副作用。
静态数据与全局变量类似,因为它们引入了一种全局状态。但是,假设静态方法是无状态的,那么它们并不像全局变量那样糟糕。
并非完全如此。 静态实际上确定了何时,何地以及多久实例化某些内容,而不是谁可以访问它。