迭代器模式和组合模式混用

迭代器模式和组合模式混用


前言


  园子里说设计模式的文章算得上是海量了,所以本篇文章所用到的迭代器设计模式和组合模式不提供原理解析,有兴趣的朋友可以到一些前辈的设计模式文章上学学,很多很有意思的。在Head
First
设计模式这本书中,也有说迭代和组合模式混用的方法,但是使用的语言是JAVA,实现起来比起C#差异还是不少。本人在做几个C#小项目的时候需要用到树形结构,也看到了Head
First
设计模式中混用迭代器和组合模式的例子,觉得如果能用C#实现,以后无疑会带来很大的帮助。下面就记录下实现过程,希望有不好的地方,各位前辈大力拍,晚生会努力改正,本文使用C#。

效果与目标


  1.能自动遍历树形结构中的所有节点。

  2.对树中所有节点进行统一管理,统一到一个根节点上。

  举个例子:文件系统,有文件夹和文件这两个类型,形成一个文件系统树形结构,使用了本文章所说的混用模式以后,能轻松对每一个结点进行自动处理,最简单的就是打印各自的名字和子文件系统或排序等。

实现过程


  下面以文件系统为例,可以根据需要灵活改变,主要讲得是思想而已。

    新建一个C#控制台,随便改个名字。


    搭建类和接口(实现组合模式)。

      1.IFileSystemNode(文件系统接口):

interface IFileSystemNode
{
String Name { set; get; }
String Path { set; get; }
List<IFileSystemNode> Children { set; get; }
IEnumerator getIterator();
void ShowName();
}

      2.FolderNode(文件夹节点类):

class FolderNode : IFileSystemNode
{
public FolderNode(String name, String path)
{
this.Name = name;
this.Path = path;
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}

private string _path;
public string Path
{
get
{
return _path;
}
set
{
_path = value;
}
}

private List<IFileSystemNode> _children = new List<IFileSystemNode>();
public List<IFileSystemNode> Children
{
get
{
return _children;
}
set
{
_children = value;
}
}

public void ShowName()
{
Console.WriteLine(Name);
}

public System.Collections.IEnumerator getIterator()
{
throw new NotImplementedException();
}
}

      3.FileNode(文件节点类):

class FileNode : IFileSystemNode
{
public FileNode(String name, String path)
{
this.Name = name;
this.Path = path;
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}

private string _path;
public string Path
{
get
{
return _path;
}
set
{
_path = value;
}
}

public List<IFileSystemNode> Children
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}

public void ShowName()
{
Console.WriteLine(Name);
}

public System.Collections.IEnumerator getIterator()
{
throw new NotImplementedException();
}
}

                 注意:以上实现了组合模式,其中getIterator方法是还没有代码的,这个需要使用迭代器模式。

    编写迭代器(实现迭代器模式)。

    在FolderNode中有子节点,但是在FileNode中没有子节点,但是因为使用了组合器模式,对于FolderNode和FileNode,都需要实现相同的契(IFileSystemNode)。所以在FolderNode中返回的迭代器是用来迭代子节点,而FileNode则不同,它根本没有子节点,那么就使用一个叫做空迭代器来满足契约。

下面分别实现具体迭代器(继承C#系统提供的IEnumerator接口)。

    
1.为FolderNode提供具体迭代器:FolderNodeIterator

class FolderNodeIterator : IEnumerator
{
private IEnumerable<IFileSystemNode> fileSystems { set; get; }
public FolderNodeIterator(IEnumerable<IFileSystemNode> _fileSystems)
{
this.fileSystems = _fileSystems;
}
private int currentIndex = -1;
public object Current
{
get { return fileSystems.ElementAt(currentIndex); }
}

public bool MoveNext()
{
if (currentIndex < fileSystems.Count() - 1)
{
currentIndex++;
return true;
}
return false;
}

public void Reset()
{
currentIndex = -1;
}
}

  新建完类以后,我们修改下FolderNode类中的getIterator方法,返回一个FolderNodeIterator实例,代码如下:

public IEnumerator getIterator()
{
return new FolderNodeIterator(_children);
}

      2.为FileNode提供具体迭代器:EmptyIterator

class EmptyIterator : IEnumerator
{

public object Current
{
get { return null; }
}

public bool MoveNext()
{
return false;
}

public void Reset()
{

}
}


View
Code

  新建完类以后,我们同样修改下FileNode类中的getIterator方法,返回一个EmptyIterator实例,代码如下:

public IEnumerator getIterator()
{
return new EmptyIterator();
}

  

  使用

  好像差不多了,我们使用使用一下这个模型:

    为了添加真实性,本演示映射了真实文件系统,请在Programe类上添加一个静态方法:Convert

private static void Convert(FolderNode root, String directoryPath)
{
foreach (var filesystempath in Directory.EnumerateFiles(directoryPath))
{
if (root.Children != null)
{
root.Children.Add(new FileNode(Path.GetFileName(filesystempath), filesystempath));
}
}

foreach (var filesystempath in Directory.EnumerateDirectories(directoryPath))
{
FolderNode newFolderNode = new FolderNode(Path.GetFileName(filesystempath), filesystempath);
root.Children.Add(newFolderNode);
Convert(newFolderNode, filesystempath);
}
}

    然后我们在Main方法中就能先映射,再使用,来看一下Main方法,其中使用了迭代器模式去迭代各个子项:


static void Main(string[] args)
{
FolderNode root = new FolderNode(@"酷狗音乐", @"C:\Users\Administrator\Desktop\\酷狗音乐");
Convert(root, @"C:\Users\Administrator\Desktop\\酷狗音乐");

IEnumerator Myiterator = root.getIterator();
while (Myiterator.MoveNext())
{
IFileSystemNode ctextIterator = (IFileSystemNode)Myiterator.Current;
ctextIterator.ShowName();
}
Console.ReadKey();
}

    我映射了桌面上的一个文件,看看文件结构:

      有一个hozin文件夹(里面有3首歌),一个L‘theme文件夹(里面有一首歌),一个文件(08开头的歌)。

    好了,运行程序,看看结果:,好像有点问题,为什么只有一个层的呢?也就是说,为什么只迭代了root节点的一层子节点,子节点的子节点还没有遍历完,这是因为FolderNodeIterator的迭代只提供了一层迭代,而不会深层迭代。所以如果想要深层迭代,使用Head
First设计模式中的思想就是:提供一个组合迭代器,用来包装FolderNodeIterator,提供深层迭代功能。下面是我在C#中的实现代码,添加这样一个类:CompositeIterator

class CompositeIterator : IEnumerator
{
public CompositeIterator(IEnumerator ienumerator)
{
temp.Push(ienumerator);
root = ienumerator;
}
IEnumerator root;
Stack<IEnumerator> temp = new Stack<IEnumerator>();
private IFileSystemNode _current;

public object Current
{
get { return _current; }
}

public bool MoveNext()
{
if (temp.Count <= 0)
{
return false;
}
if (temp.Peek().MoveNext())
{
_current = temp.Peek().Current as IFileSystemNode;
IEnumerator ienumerator = _current.getIterator();
if (ienumerator.MoveNext())
{
ienumerator.Reset();
temp.Push(ienumerator);
}
}
else
{
temp.Pop();
MoveNext();
}
if (temp.Count <= 0)
{
return false;
}
else
{
return true;
}
}

public void Reset()
{
temp.Clear();
temp.Push(root);
}
}

  然后,修改FolderNode类中的getIterator方法如下:

public System.Collections.IEnumerator getIterator()
{
return new CompositeIterator(new FolderNodeIterator(this._children));
}

  包装完以后,再次运行:。OK大功告成

总结


    为了适应真实项目,可以改的点有很多:

      1.这里只有FolderNode和FileNode,在实际项目中可能不止,可以添加,只要继承同一个接口(这里是IFileSystemNode),那么就能像皇帝发号命令一样命令所有子子孙孙做事情了(在root节点上调用IFileSystemNode上声明有的方法)。

      2.添加契约方法,例如像要对每一个节点进行排序Sort,直接添加一个方法,然后子孙各自实现方法,最后调用root节点的Sort。

      3.这里的遍历使用前序遍历,遍历树的所有节点,但是也可以使用您喜欢的方式,只要修改组合迭代器。

源码下载

迭代器模式和组合模式混用,布布扣,bubuko.com

时间: 2024-11-03 21:43:20

迭代器模式和组合模式混用的相关文章

(38)23种设计模式研究之九【迭代器模式和组合模式】

一.定义 迭代器可以认为是一个指针,可以遍历容器的指针.迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器物件的内容迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址.迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器.然而迭代器有很多不同的能力,它可以把抽象容器和

12结构型模式之组合模式

概念 Composite模式也叫组合模式,是构造型的设计模式之一.通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树. 角色和职责 Component (树形结构的节点抽象) - 为所有的对象定义统一的接口(公共属性,行为等的定义) - 提供管理子节点对象的接口方法 - [可选]提供管理父节点对象的接口方法 Leaf (树形结构的叶节点) Component的实现子类 Composite(树形结构的枝节点) Component的实现子类 适用于: 单个对象和组合对象的使用具有一

迭代器模式和组合模式

迭代器模式: 提供一种方法顺序访问聚合对象内的各个元素,而又不暴露其内部的表示 实现Iterator接口的hasNext()以及next()方法 组合模式: 允许你将对象组合成树形结构来表现"整体/部分"层次结构,组合能让客户以一致的方式处理个别对象以及对象组合

设计模式-迭代器模式和组合模式

1.迭代器模式完成的功能是和迭代器一样的,封装了对对象的顺序遍历,因为子类的对象集合的存储方式可能并不一致.但是存储的对象是一致的. public classItem{ .....//各种属性 } public class Set1{ item[] items; ... public Iterator createIterator(){ return new ItemIterator(items); } } public class Set2{ ArrayList items; ... publ

迭代器模式,组合模式 -- 学习HeadFirst设计模式记录

迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 组合模式   :允许你将对象组合成树形结构来表现"整体/部分"层次结构.组合能让客户以一致的方式处理个别对象以及对象组合. 单一原则:一个类应该只有一个引起变化的原因. 迭代器模式示例代码:   #include <iostream>#include <iomanip>  // cout格式控制#include <string>#include <vector&

结构型模式之组合模式

概述 对于树形结构,当容器对象(如文件夹)的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象(可以是容器对象,也可以是叶子对象)并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理.由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下我们希望一致地处理它们,因为对于这些对象的区别对待将会使得程序非常复杂.组合模式为解决此类问题而诞生,它可以让叶子对象和容器对象的使用具有一致性 定义 组合模式(Co

C++外观模式和组合模式

外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来.客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构.DP一书的定义:为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用.举个编译器的例子,假设编译一个程序需要经过四个步骤:词法分析.语法分析.中间代码生成.机器码生成.学过编译都知道,每一步都很复杂.对于编译器这个系统,就可以使用外观模式.可以定义

java23中设计模式之组合模式

package com.bjsxt.composite; /** * 抽象组件 * @author Administrator * */ public interface Component { void operation(); } //叶子组件 interface Leaf extends Component { } //容器组件 interface Composite extends Component { void add(Component c); void remove(Compon

迭代器与组合模式

迭代模式与组合模式要点: 1.迭代器允许访问聚合的元素,而不需要暴露它的内部结构 2.迭代器将遍历聚合的工作封装进一个对象中 3.当使用迭代器的时候,我们一来聚合提供遍历 4.迭代器提供了一个通用的接口,让我们遍历聚合的项时,就可以使用多态机制 5.我们应该努力让一个类只分配一个责任 6.组合模式提供一个结构,可同时包容个别对象和组合对象 7.组合模式允许客户对个别对象以及组合对象一视同仁 8.组合结构内的任意对象称为组件,组件可以使组合,也可以是叶子节点 9.在实现组合模式时,有许多设计上的折