虽然泛型出现已有多年,连Java都早已借鉴引入了泛型(虽然是语法糖),可是用泛型的编程思维方式并没有得到相应的普及。一方面是由于过去大量的Framework仍然是在非泛型时代写成的,另一方面泛型的设计模式没有得到发展,改变的时候该到了。
来举一个例子说明这两点。我们如果写过网络数据抓取的代码,应该熟悉这样的代码:
var request = WebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest; |
或者这么写,也是一样:
var request = HttpWebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest; |
大家可想过,为什么每次都要as一下?
类似的情况还有,比如做图像处理的弟兄会熟悉:
var bm = Image.FromFile("e:\\me.jpg") as Bitmap; |
和
var bm = Bitmap.FromFile("e:\\me.jpg") as Bitmap; |
我想过,但没想明白。上面两种写法,都是调用父类的工厂方法,实际返回了一个子类的实例。显然,即使不了解OCP,凭直觉也应该想到,父类的实现中不应该被子类所决定。写WebRequest和Image的前辈可能也觉得直接返回子类实例不妥,所以阴险地把方法签名的返回类型改成了父类。
虽然这种行径值得严重鄙视。但.NET程序员大都是人云亦云,照葫芦画瓢的好学生,所以这个问题多年了也没有修改。
理想的设计应该是这样:父类的每个子类,都有独立的工厂方法,返回其自身的实例。这样做法,在泛型出现前非常笨拙,得不偿失,但有了泛型,就可以精巧地实现。
以模拟Image类为例,Image和BitMap实现如下:
|
Image自身的工厂方法,就没有存在的必要了。
可以简单地测试一下:
|
输出结果如下:
|
为了让大家更熟悉一下,再举一个实现数据结构中的二叉树作例子。
传统的树节点类,无论无论C/C++/Java都是类似这样:
|