什么时候应该写静态方法?

所以我理解静态方法或字段是什么,我只是想知道何时使用它们。 也就是说,在编写代码时,设计适合使用静态方法和字段。

一种常见的模式是使用静态方法作为静态工厂,但这可以通过重载构造函数来轻松完成。 正确? 例如:

var bmp = System.Drawing.Bitmap.LoadFromFile("Image01.jpg"); 

至于静态场,是否最好使用singelton-objects?

当您使用静态工厂时,它可以更好地了解意图 – 它还允许您拥有采用相同参数类型但具有不同含义的不同工厂。 例如,假设Bitmap有LoadFromResource(字符串) – 就不可能有两个构造函数都接受字符串。

编辑 :来自评论中的stevemegson

静态工厂也可以返回null,并且可以更容易地返回从缓存中获取的实例。 我的许多类都有一个静态FromId(int)来从主键获取实例,如果有的话,返回一个现有的缓存实例。

静态方法通常对不需要来自类实例(来自this实例)的任何数据的操作有用,并且可以仅使用其参数来执行其预期目的。
一个简单的例子就是方法Point::distance(Point a, Point b); 计算两点之间的距离,不需要实例。

静态字段对于那些不会经常更改并且由类的所有实例使用的常量非常有用。

我会说只要你拥有独立于实例状态的函数,就使用静态方法,即。 不依赖于任何实例字段。

方法所依赖的非局部状态越少,理解就越容易,因此static对代码的读者来说是一个有用的信号。

我通过记住实例方法在单个对象上/内部工作,而静态方法为类做了一些事情,我保持清楚。

在LoadFromFile()的情况下,您需要一个静态方法,因为如果加载失败,您需要一个空引用 – 该实例尚不存在。 如果您将其实现为构造函数,则必须在失败时抛出exception。

静态的其他好用途:比较(obj a,obj b),删除(obj a)数据对象(一个对象不能删除自己,因为它的引用仍然存在),或者是程序代码的静态类,实际上不能在一个对象中建模。

以下是您可能希望使用静态方法的一些示例:

1)当函数没有使用任何成员变量时。 您不必在此处使用静态方法,但如果您这样做,通常会有所帮助。

2)使用工厂方法创建对象时。 如果您不知道要提前创建的类型,则特别需要它们:例如

 class AbstractClass { static createObject(int i) { if (i==1) { return new ConcreteClass1(); } else if (i==2) { return new ConcreteClass2(); } } } 

3)当您控制或以其他方式跟踪该类的实例化数量时。 Singleton是最常用的例子。

4)声明常量时。

5)对类的多个对象进行操作的操作,例如排序或比较,并且不依赖于任何特定实例。

6)在第一次实例化对象之前必须进行特殊处理。

只要有一个不依赖于该类的特定对象的函数,就应该使用静态方法。

添加static关键字没有任何害处:它不会破坏任何引用它的代码。 因此,例如,无论您是否拥有’static’关键字,以下代码均有效:

 class Foo { public Foo(){} public static void bar(){} // valid with or without 'static' public void nonStatic(){ bar(); } } ... Foo a = new Foo(); a.bar(); 

因此,您应该为任何方法添加“静态”。

当类的客户端没有要使用的类的实例时,您可以使用静态方法。 例如,Singleton设计模式用于确保系统中只存在一个类的实例。 它要求Singleton的构造函数是私有的,以便客户端不能创建任何实例。

因此,如果您无法创建实例,那么如何访问类的实例方法? 通过调用返回类的Singleton实例的静态方法。

这当然只是一种情况,但还有很多其他情况。

当方法不属于特定对象时,请使用静态方法。

例如,如果查看.NET框架中的Math类,您将看到所有方法都是静态的。 为什么? 因为没有理由必须创建一个对象来使用这些方法。 当你想要的只是某个东西的绝对值时,你为什么要创建Math类的对象? 不,没有理由这样做,因此,该方法是静态的。

所以当你设计课程时,问问自己:

此方法是属于对象还是类本身?

如果方法修改了对象的状态,则该方法属于对象。 如果方法不修改特定对象,则很可能是静态的。

另一个例子,假设您想知道创建的类的对象数量(不要问我为什么……)。 对于此任务,您可以创建一个静态方法GetNumberOfObjects() (您显然需要一个静态字段,以及构造函数中的一些代码)。 你可能会问,为什么我会让它静止不动。 好吧,回答上面的问题,你会看到。 该方法不属于任何特定对象。 此外,它不会修改任何对象。

我希望这是有道理的。