【发布时间】:2010-09-17 04:24:24
【问题描述】:
所以我了解什么是静态方法或字段,我只是想知道何时使用它们。也就是说,在编写代码时,哪些设计适合使用静态方法和字段。
一种常见的模式是将静态方法用作静态工厂,但这也可以通过重载构造函数来轻松实现。正确的?例如:
var bmp = System.Drawing.Bitmap.LoadFromFile("Image01.jpg");
对于静态字段,创建单例对象是他们的最佳用途吗?
【问题讨论】:
所以我了解什么是静态方法或字段,我只是想知道何时使用它们。也就是说,在编写代码时,哪些设计适合使用静态方法和字段。
一种常见的模式是将静态方法用作静态工厂,但这也可以通过重载构造函数来轻松实现。正确的?例如:
var bmp = System.Drawing.Bitmap.LoadFromFile("Image01.jpg");
对于静态字段,创建单例对象是他们的最佳用途吗?
【问题讨论】:
静态方法通常适用于不需要来自类实例(来自this)的任何数据并且可以仅使用它们的参数来执行其预期目的的操作。
一个简单的例子是一个方法Point::distance(Point a, Point b);,它计算两点之间的距离并且不需要实例。
静态字段对于不经常更改并且被类的所有实例使用的常量非常有用。
【讨论】:
当您使用静态工厂时,它可以更好地了解意图 - 它还允许您拥有不同的工厂,它们采用相同的参数类型但具有不同的含义。例如,想象一下如果 Bitmap 有 LoadFromResource(string) —— 不可能有两个都接受 string 的构造函数。
编辑:来自 cmets 中的 stevemegson
静态工厂也可以返回 null,并且可以更轻松地返回它从缓存中获取的实例。我的许多类都有一个静态 FromId(int) 来从主键中获取一个实例,如果我们有一个缓存实例,则返回一个现有的缓存实例。
【讨论】:
只要你有独立于实例状态的函数,我会说使用静态方法,即。不依赖于任何实例字段。
方法所依赖的非本地状态越少,就越容易理解,因此static 对代码读者来说是一个有用的信号。
【讨论】:
我通过记住实例方法在单个对象上/内部工作,而静态方法为类做一些事情来保持清楚。
在 LoadFromFile() 的情况下,您需要一个静态方法,因为如果加载失败,您需要一个空引用 - 实例还不存在。如果您将其实现为构造函数,则必须在失败时抛出异常。
静态的其他良好用途:Compare(obj a, obj b)、Delete(obj a) 用于数据对象(对象不能删除自身,因为它的引用仍然存在),或用于诚实的过程代码的静态类无法在对象中建模。
【讨论】:
当方法不属于特定对象时使用静态方法。
例如,如果您查看 .NET 框架中的 Math 类,您会看到
所有方法都是静态的。为什么?因为没有理由必须创造
使用方法的对象。为什么要创建一个对象
Math 类,什么时候你想要的只是某物的绝对值?不在这里
没有理由这样做,因此该方法是静态的。
所以当你设计一门课时,问问自己:
这个方法是属于一个对象,还是属于类本身?
一个方法属于一个对象,如果它修改了对象的状态。如果 该方法不会修改特定对象,它很可能是静态的。
另一个例子,假设你想知道一个类有多少个对象
这是创建的(不要问我为什么......)。对于此任务,您可以创建一个
静态方法GetNumberOfObjects()(你显然需要一个静态字段,
以及构造函数中的一些代码)。为什么我要让它是静态的,你可能会
问。那么,回答上面的问题,你会看到。该方法不
属于任何特定对象。此外,它不会修改任何对象。
我希望这是有道理的。
【讨论】:
只要您有一个不依赖于该类的特定对象的函数,您就应该使用静态方法。
添加 static 关键字并没有什么坏处:它不会破坏任何引用它的代码。因此,例如,无论您是否具有“静态”关键字,以下代码都是有效的:
class Foo
{
public Foo(){}
public static void bar(){} // valid with or without 'static'
public void nonStatic(){ bar(); }
}
...
Foo a = new Foo();
a.bar();
因此,您应该将“静态”添加到您可以使用的任何方法中。
【讨论】:
以下是您可能希望使用静态方法的一些示例:
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) 在第一次实例化对象之前必须进行特殊处理时。
【讨论】:
当类的客户端没有要使用的类的实例时,您可以使用静态方法。例如,单例设计模式用于确保系统中仅存在一个类的一个实例。它要求 Singleton 的构造函数是私有的,这样客户端就不能创建实例。
如果你不能创建一个实例,你如何访问类的实例方法呢?通过调用返回类的 Singleton 实例的静态方法。
这当然只是一种情况,但还有很多其他情况。
【讨论】: