DotNet中的迭代模式和组合模式
DotNet中设计的类或者框架大部分都可以跟某个设计模式对应的上,因此理解一些设计模式的内容有助于提高对dotnet的认识,可以更深刻的认识这些类的使用。显然dotnet中的类的设计绝对称得上是专业的,我们在设计自己的类时可以作为参考,提高设计的质量。
最近在HeadFirst DesignPattern一书中看到Iterator和Composite模式的介绍,书中讲的内容是以java为例子,讲述了如何使用Iterator接口去实现对集合的迭代,应用Iterator模式。之后介绍了使用统一基类的方法去管理子节点和父节点,从而实现Compostie模式的应用。看完之后,我觉得这些应用同样在dotnet中也是随处可见的,只不过类的名称有些不同,而且在dotnet方面用起来还更加的方便。接下来看看dotnet中分别使用了这两种设计模式的实例。
对于迭代模式,在java5之前只能通过Enumeration类来实现迭代,具体方式是在每个类中添加一个返回Enumeration对象的;之后就出现了更加高级的Iterator类,具体用法都差不多,但是有了类似于dotnet的foreach的迭代方式,但是仍可以通过方法返回一个迭代器。而dotnet中的实现方式也基本类似,dotnet中利用IEnumerator接口实现Iterator的功能,但是dotnet要求集合类实现IEnumerable接口才可以用foreach方式迭代,然后每个对象返回各自的IEnumerato。当然原始的方法也是支持的,也就是手动的返回一个IEnumerator,然后循环的调用next方法。另外dotnet中返回IEnumerator的方式还有更简便的方法,可利用yield关键字实现,具体可查看msdn。两种语言的最终显示目的都是相同的,那就是通过一个统一的基类或接口实现对不同集合的迭代,实现抽象与具体实现的分离。
接下来是组合模式,这种模式的对于实现层级关系的处理有很灵活的扩展性,同样也是利用了基类或统一接口的方式(似乎设计模式都离不开基类或接口)。这种模式的具体做法是用一个相同的基类去对待子节点和父节点,这样在client调用时就不需要去考虑到底是什么节点,只知道它是一个节点。这种层级关系的例子很容易让人想到xml。dotnet中通过XmlNode去统一管理所有的Xml节点,然后提供HasChildNode的方法判断是否有子节点,这个方法通常用于递归的迭代所有的子节点;在IO方面,dotnet提供了FileSystemInfo基类去统一管理文件和文件夹,这也是种典型的层级关系。不过在IO中,文件和文件夹具有自己各自不同名称的类,FileInfo和DirecotryInfo。java也有类似的方式,不过在java中基类统一了大部分的方法,比如某些子节点调用会出问题的方法都放在基类中。dotnet则比较安全,但是要调用具体各自的方法时就有点点麻烦;gui方面的也有体现,比如典型的Menu和MenuItem,这种实现方式有一点点差别,那就是MenuItem继承了Menu,更明显的体现出父子关系,同样也达到了统一接口的目的,使用的时候通过IsParent判断是否为父节点。
组合模式带来的方便更多体现在递归迭代,进一步跟迭代器结合起来将会带来极高的灵活性。