静态工厂是指用一个静态函数返回一个实例,一个典型的例子就是Graphics类,例如:
public static Graphics FromHdc(IntPtr hdc);
public static Graphics FromHwnd(IntPtr hwnd);
public static Graphics FromImage(Image image);
Graphics类没有提供公开的的构造函数,必须用这些静态函数的构造对象。构造函数跟静态工厂都是生成实例的一种设计,静态工厂有什么优缺点?
静态工厂的优点:
1、可以提供很直观、具有描述性的函数名称,例如上面的例子,一看就知道用什么类型的数据建立Graphics对象。
2、一个类不能有两个签名一样的的构造函数,即不能参数类型跟排列一样的构造函数。上面例子中,两个函数的参数都是IntPtr,不会混淆。
3、可以返回相同的、已经存在实例,提高重用性,提高性能。一个典型的例子是Brushs.Red属性,返回一个红色的SolidBrush实例。
4、既可以返回派生类对象,也可以返回基类对象,或者说可以返回任何东西。例如 Brushs.Red属性的返回类型是Brush,虽然内部构建的是SolidBrush。
静态工厂的缺点:
1、如果只提供静态工厂的方法,不提供公开的构造函数,则这个工厂不能具有派生类,即变成一个sealed 类了。(其实这个可以是个优点,更高的封装性)
2、构造函数跟类名具有一样的名字,使得人一看到它就知道是构造函数,静态工厂的函数没有这个特点。
最后说说Brushs这个画刷工厂,一个容易使用错的地方,例如:
Brush b1 = Brushes.Red;
b1.Dispose();
......
Brush b2 = Brushes.Red;
这会导致第二次取得的Brush b2不能用,因为b1、b2都是指向同一个对象,已经被Dispose()了。
所以使用完Brushes工厂的生成的Brush,不能调用Dispose()释放,要主动释放就自己生成Brush。
我们再看看例如Brushs.Red是怎么实现的:
public static Brush Red
{
get
{
Brush brush = (Brush) SafeNativeMethods.ThreadData[RedKey];
if (brush == null)
{
brush = new SolidBrush(Color.Red);
SafeNativeMethods.ThreadData[RedKey] = brush;
}
return brush;
}
}
SafeNativeMethods.ThreadData是一个 IDictionary的实现。
能看明白这个实现,就明白为什么了。
技术讨论的QQ群: 2514097 或 10987609