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

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

前言

  园子里说设计模式的文章算得上是海量了,所以本篇文章所用到的迭代器设计模式和组合模式不提供原理解析,有兴趣的朋友可以到一些前辈的设计模式文章上学学,很多很有意思的。在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();}
View Code

      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();}}
View Code

      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();}}
View Code

                 注意:以上实现了组合模式,其中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;}}
View Code

  新建完类以后,我们修改下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);}}
View Code

    然后我们在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);}}
View Code

  然后,修改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.这里的遍历使用前序遍历,遍历树的所有节点,但是也可以使用您喜欢的方式,只要修改组合迭代器。

 

                                   源码下载

转载于:https://www.cnblogs.com/Jarvin/p/3735460.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/493232.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python实现可扩容队列

#coding:utf-8 """ fzh created on 2019/10/15 构建一个队列 """ import datetimeclass LoopQueue(object):def __init__(self, n10):self.arr [None] * (n1) # 由于特意浪费了一个空间&#xff0c;所以arr的实际大小应该是用户传入的容量1sel…

5G 产业链重要投资节点

来源&#xff1a;兴业证券 ▌5G:大通信容量及超低延时&#xff0c;未来多项应用的基础5G:高工作频率以及频谱带宽带来高通信容量5G(5thgeneration)是指第五代移动电话通信标准。3GPP(第三代合作伙伴计划&#xff0c;电信标准化机构)将5G标准分为了NSA(非独立组网)和SA(独立组网…

Kneser猜想与相关推广

本文本来是想放在Borsuk-Ulam定理的应用这篇文章当中。但是这个文章实在是太长&#xff0c;导致有喧宾夺主之嫌&#xff0c;从而独立出为一篇文章&#xff0c;仅供参考。$\newcommand{\di}{\mathrm{dist}}$ &#xff08;图1&#xff1a;Kneser叙述他的猜想原文手稿&#xff09;…

python .py文件变为.so文件进行加密

&#xff11;.mytest.py 需要加密的内容 #coding:utf-8 import datetimeclass Today():def get_time(self):print(datetime.datetime.now())def say(self):print("hello word!")today Today() today.say() today.get_time() 2.执行setup.py 也就是加密脚本 from…

从技术上解读大数据的应用现状和开源未来

来源&#xff1a;网络大数据作者 | 韩锐、 Lizy Kurian John、詹剑锋摘要&#xff1a;近年来&#xff0c;随着大数据系统的快速发展&#xff0c;各式各样的开源基准测试集被开发出来&#xff0c;以评测和分析大数据系统并促进其技术改进。然而&#xff0c;迄今为止&#xff0c;…

十八岁华裔天才携手「量子计算先驱」再次颠覆量子计算

来源&#xff1a;机器之心编译参与&#xff1a;刘晓坤、李泽南摘要&#xff1a;量子计算再一次「被打败了」。今年 8 月&#xff0c;刚刚年满 18 岁的 Ewin Tang 证明了经典算法能以和量子计算机相近的速度解决推荐问题&#xff0c;这位天才少女&#xff08;更正&#xff1a;不…

resnet系列+mobilenet v2+pytorch代码实现

一.resnet系列backbone import torch.nn as nn import math import torch.utils.model_zoo as model_zooBatchNorm2d nn.BatchNorm2d__all__ [ResNet, resnet18, resnet34, resnet50, resnet101, deformable_resnet18, deformable_resnet50,resnet152]model_urls {resnet18:…

广度优先搜索(BFS)与深度优先搜索(DFS)

一.广度优先搜索&#xff08;BFS&#xff09; 1.二叉树代码 # 实现一个二叉树 class TreeNode:def __init__(self, x):self.val xself.left Noneself.right Noneself.nexts []root_node TreeNode(1) node_2 TreeNode(2) node_3 TreeNode(3) node_4 TreeNode(4) node_…

骁龙855在AI性能上真的秒杀麒麟980?噱头而已

来源&#xff1a;网易智能摘要&#xff1a;前段时间的高通发布会上&#xff0c;有关骁龙855 AI性能达到友商竞品两倍的言论可谓是赚足了眼球。高通指出&#xff0c;骁龙855针对CPU、GPU、DSP都进行了AI计算优化&#xff0c;结合第四代AI引擎可以实现每秒超过7万亿次运算&#x…

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 转载

http://heylinux.com/archives/1004.html MySQL主从复制&#xff08;Master-Slave&#xff09;与读写分离&#xff08;MySQL-Proxy&#xff09;实践 Mysql作为目前世界上使用最广泛的免费数据库&#xff0c;相信所有从事系统运维的工程师都一定接触过。但在实际的生产环境中&am…

深度解析AIoT背后的发展逻辑

来源&#xff1a;iotworld摘要&#xff1a;AI与IoT融合领域近年来一片火热&#xff0c;不论是资本市场&#xff0c;还是大众创业&#xff0c;无不对其表现出极大的热情。AIoT领域中人机交互的市场机会自2017年开始&#xff0c;“AIoT”一词便开始频频刷屏&#xff0c;成为物联网…

ubuntu安装Redis+安装mysql(配置远程登录)+安装jdk+安转nginx+安转teamviewer+安装terminator+安装sublime

一&#xff0e;Ubuntu 安装 Redis sudo apt-get update sudo apt-get install redis-server redis-server 启动 修改redis配置 远程访问: sudo vim /etc/redis/redis.conf 注释掉本机ip: 有坑的地方 #bind 127.0.0.1  service redis-server restart redis-cli ping …

深入理解SQL注入绕过WAF与过滤机制

知己知彼&#xff0c;百战不殆 --孙子兵法 [目录] 0x0 前言 0x1 WAF的常见特征 0x2 绕过WAF的方法 0x3 SQLi Filter的实现及Evasion 0x4 延伸及测试向量示例 0x5 本文小结 0x6 参考资料 0x0 前言 促使本文产生最初的动机是前些天在做测试时一些攻击向量被WAF挡掉了&#xff0c;…

预测|麦肯锡预测2030年:1亿中国人面临职业转换,全球8亿人被机器人取代

来源&#xff1a;先进制造业摘要&#xff1a;纵观人类技术的发展历程&#xff0c;往往遵循一个固定的规律&#xff0c;即先是概念萌芽&#xff0c;然后经历市场炒作&#xff0c;资本蜂拥&#xff0c;结果潮水退去&#xff0c;泡沫破灭。而繁华落尽后&#xff0c;才会经历技术成…

计算polygon面积和判断顺逆时针方向的方法

一&#xff0e;利用shapely求polygon面积 import shapelyfrom shapely.geometry import Polygon, MultiPoint # 多边形# box1 [2, 0, 4, 2, 2, 4, 0, 2, 0, 0]box1 [2, 0, 4, 2, 2, 4, 0, 2, 2, 2]poly_box1 Polygon(np.array(box1).reshape(-1,2))print(poly_box1)print(p…

亚洲与非洲:中国支付巨头的海外进击

来源&#xff1a;资本实验室摘要&#xff1a;当下&#xff0c;对国人消费影响最大的两家互联网公司莫过于阿里巴巴和腾讯。这两大公司将大量消费级应用整合在自身的平台上&#xff0c;已经彻底改变了许多人的餐饮、购物、出行、旅游等生活方式&#xff0c;而移动支付是其中最基…

利用已有的标注文字信息制作fake数据

from PIL import Image, ImageDraw, ImageFont, ImageFilter import random import glob import numpy as np import os import cv2 from nespaper_semantics import seg_str 1. 从文字库随机选择10个字符 2. 生成图片 3. 随机使用函数# 从字库中随机选择n个字符 def sto_choic…

汽车芯片:半导体芯片巨头加速成长

来源&#xff1a;乐晴智库精选伴随汽车智能化提速&#xff0c;汽车半导体加速成长。2017年全球汽车销量9680万辆(3%);汽车半导体市场规模288亿美元(26%)&#xff0c;增速远超整车。汽车半导体按种类可分为功能芯片MCU(MicrocontrollerUnit)、功率半导体(IGBT、MOSFET等)、传感器…

将MSRA-TD500标签转换成逆时针输出标签+labeleme json格式转四个点的txt

一&#xff0e;MSRA-TD500 : http://www.iapr-tc11.org/mediawiki/index.php/MSRA_Text_Detection_500_Database_%28MSRA-TD500%29 #coding:utf-8 """ fzh created on 2019/12/6 将MSRA-TD500数据标签转换成按逆时针输出 也即  index,difficulty label,x,y,w…

一文看尽2018全年AI技术大突破

来源&#xff1a;量子位摘要&#xff1a;2018&#xff0c;仍是AI领域激动人心的一年。这一年成为NLP研究的分水岭&#xff0c;各种突破接连不断&#xff1b;CV领域同样精彩纷呈&#xff0c;与四年前相比GAN生成的假脸逼真到让人不敢相信&#xff1b;新工具、新框架的出现&#…