设计模式(十一):从文Finder中认识组合模式(Composite Pattern)

上一篇博客中我们从从电影院中认识了"迭代器模式"(Iterator Pattern),今天我们就从文件系统中来认识一下“组合模式”(Composite Pattern)。说到组合模式,在此我想聊一下在类图中有组合与聚合的关系,这两者都是整体和部分的关系,只是整体与部分的依赖度不同。在聚合关系中,整体强烈依赖于部分,而部分脱离于整体将没有存在的意义,比如你身上的器官与你的关系就是聚合关系。而对于组合关系来说整体与部分的依赖就相对于小一些,离开彼此也是可以独立生存的,比如员工与公司的关系,就是组合关系。

言归正传,今天我们来介绍一下“组合模式”。下方就是组合模式的定义:

组合模式:允许你将对象组合成树形结构来表现整体/部分层次结构。组合能让客户以一致的方式处理个别对象已经对象组合

组合模式也就是将多个独立的个体组合到一块,不过组合时是有层级关系的,而这些层级关系是“树”形的关系。典型的树状层级关系就是我们的文件系统,下方截图就是我们资源管理器的一个文件层级的截图。可以明确的看出下方是树状的层级关系。今天我们的任务就是使用“组合模式”模拟下方的文件结构。从下方的截图中我们可以分析出文件总体上可以分为两种类型,一个是文件夹,在一个就是真正有内容的文件。文件夹是一种容器,它不仅可以存储文件还可以存储文件夹。文件夹可以存储文件以及其他文件夹,这一特性就决定文件系统是一个树形结构。

       

 

一、模拟“文件系统”实现的类图设计

依旧是老套路,我们要使用代码结合“组合模式”来模仿上面截图中的文件结构,首先我们先来设计类图,然后在根据我们设计的类图来给出代码实现。上面我们已经提到过文件夹就是可以存储其他文件夹和文件的容器,所以在我们设计实现是打算使用Dictionary(字典)来实现这一容器的特性,至于如何去实现下方会给出具体的实现方式。下方的类图就是我们要实现的“文件系统”的类图,当然我们是模拟的,尽量的简化了一些操作。下方也使用了组合模式,Folder类就是组合文件夹与文件的地方,稍后会给出具体的说明。

首先我们来介绍下方黄色框中的文件类型协议与该协议的延展。FileType是我们所有文件的协议,无论是文件夹还是具体文件都遵循该协议,该协议中给出了文件以及文件夹的必要操作。在该协议的默认延展中给出了协议中那些只需要文件夹实现而具体文件不需要实现的方法,如addFile()、deleteFile()方法,只有文件夹容器才会有这些方法。该协议的具体呢绒如下类图中黄框中的内容所示。

然后是红框中的部分,红框中是我们文件夹的实现,也是我们组合模式的核心模块。经过观察Folder(文件夹)类,我们不难发现Folder不仅仅遵循了FileType接口,还依赖于FileType接口。因为Folder是文件的一种类型,所以要遵循FileType接口。同时Folder是文件的容器,可以存放所有的文件和文件夹(也就是遵循FileType接口的所有类),所以Folder依赖于FileType接口。这个特性决定了组合模式有着树形结构。

最后是绿框中的部分,该部分的代码比较单纯。绿框中是具体文件的类。该模块有一个基类,也就是BaseFile。所有的具体文件都继承自BaseFile,因为BaseFile也是文件的一种所以也需要遵循FileType协议。因为具体文件不是容器,不需要实现addFile()等容器使用到的方法。因为具体文件遵循了FileType协议,而Folder依赖于FileType协议,所以Folder可以存储具体文件。整体的类图如下所示:

 

 

 

二、“文件系统”的代码实现

有了上面的类图,再给出相应的代码实现就容易的多了。接下来我们就根据上面的类图,给出相应的Swift代码实现。首先我们会给出FileType协议以及其延展的实现,具体代码片段如下所示。getFileName()方法用户获取文件名,addFile(file)用于文件夹添加文件,deleteFile(file)用于文件夹删除文件,display()用于打印文件名。FileType延展中给出了具体文件不需要实现的方法,所以在延展中给出了一个默认的实现,类似于抽象类中的方法实现。因为在协议延展中给出了方法的默认实现,所以在文件类中的可以不给出协议延展中的方法。FileType与其延展的代码段如下所示。

    

 

实现完相关的接口和扩展后就开始实现我们的具体类了,接下来我们将要给出组合模式的核心类Folder(容器类)。下方的Folder就是我们用代码实现的文件夹,Folder遵循了FileType接口,并给出了相应方法的具体实现。在Folder中我们要注意一下files属性,该属性就是组合的聚集地。我们可以看出files的类型是一个字典,字典的key是String类型,而字典的Value是FileType类型。也就是说files中可以存储遵循FileType协议的所有类,也就是files中可以存储文件和文件夹。“组合模式”在此处的提现就是文件以及文件夹在一块进行组合会生成一个新的文件夹。

下方还需要注意的就是Folder中的display()方法。该方法是遍历files数组,然后取出其中的文件或者文件夹对象,然后调用这些对象的display()方法。这样就会输出当前文件夹下所有的文件的名称。Folder文件夹类的具体实现方式如下所示:

   

 

上面给出了文件夹的实现,接着我们要实现另一种文件类型,就是具体的文件了。在实现具体文件时,我们定义了一个具体文件的基类,就是BaseFile。当然BaseFile也遵循与FileType协议,这就是我们面向接口编程。在BaseFile基类中我们给出了所有文件所共有的方法,比如getFileName()和display()方法。接着我们又实现了两个特定的文件类型,一个Swift源文件SwiftFile,另一个就是Objective-C源文件ObjCFile。这两个具体的文件都继承自BaseFile类。具体代码实现如下所示:

    

 

三、测试用例

接下来就到了测试用例的部分了,也就是上面类图中的Client的部分。Client就是该文件系统的使用者,从类图中我们可以看出来,Client依赖于FileType接口而不依赖于具体实现。因为我们是在Xcode中的Playground中做的测试,所以我们就没有给出具体的Client类。但是下方代码就等同于Client类中的代码。下方就是我们的测试用例我们构建了本文开头的文件目录结构,并输出了文件夹下所有文件的名称。测试用例与输出结果如下所示:

    

至此我们的“组合模式”的一个完整示例就执行完了。

同样今天的Demo也会在github上进行分享,分享地址为:https://github.com/lizelu/DesignPatterns-Swift

 

转载于:https://www.cnblogs.com/ludashi/p/5439128.html

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

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

相关文章

Activity(二)

多个Activity之间的调用 建立一个Activity 配置layout文件夹下fragment_main.xml文件 在layout下新建other.xml文件 xml文件创建的id需要编译才能生成 在同一工程src文件夹下新建class文件 查找id并作关联 加入监听器,调用另一个Activity的类 调用监听器 注&#xf…

php用asp文件js,asp下用fso生成js文件的代码

asp下用fso生成js文件的代码更新时间:2008年06月24日 23:47:54 作者:asp下使用fso生成js代码的方法Set fso Server.CreateObject("Scripting.FileSystemObject")set fdfso.createtextfile(server.MapPath("../category.js"),true)…

relativelayout中按键不能点_CNC | M80/M800系列系统常见按键和外部存储器故障

一、按键无效现象1.操作人员对机床操作时画面无反应现象M80/M800系列系统在使用键盘或触摸屏输入时,请勿连击键盘按键,输入一 次即可。键盘每向NC输入一次,NC系统需要计算一次,连续的多次重复输入,NC多次重复计算、显示…

vs2015如何连接oracle,VS2015中C#连接Oracle数据库

硬件环境:Win10 64位 VS2015 ODP.Net for VS2015配置ODP.NetOracle Developer Tools for Visual Studio 12.1.0.2.4 下载次文件Oracle Data Provider for .NET 4 12.1.0.2.0Oracle Providers for ASP.NET 4 12.1.0.2.0下载完成后运行MSI安装程序进行安装&#xff0…

sql数据导入错误代码: 0x80004005_PL/SQL 非预定义异常、自定义异常处理、RAISE_APPLICATION_ERROR...

抛出异常Oracle有三种类型的异常错误:1. 预定义(Predefined)异常ORACLE预定义的异常情况大约有24个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发。2. 非预定义(Pr…

腾讯视频过滤广告简略办法

转载于:https://www.cnblogs.com/rgqancy/articles/5485409.html

Linux系统查看系统硬件,linux怎么查看系统硬件信息

有时候想查看电脑中的系统硬件信息不知道怎么办下面是学习啦小编带来的关于linux怎么查看系统硬件信息的内容,欢迎阅读!linux怎么查看系统硬件信息?查看cpu:lscpu命令,查看的是cpu的统计信息.blueblue-pc:~$ lscpuArchitecture: i686 #cpu架…

designer pyqt5 界面切换_PyQt5快速上手基础篇3-设置窗口标题和图标

前言本节我们为QT Designer生成的UI界面添加图标和窗口标题。一、实例运行1. QT Designer设计UI打开designer.exe,使用默认的Main Window创建,直接点击Create按钮即可设计UI图如下,并保存为test.ui2 将test.ui转换为ui_test.py进入ui_test.py目录&#x…

linux系统gpu test,轻量级显卡测试软件GpuTest 0.4.0版下载,支持windows Linux MAC-站长资讯中心...

说到显卡测试,我们一定会想到3D Mark,可是看着3D Mark那几百兆的大小和小水管的网速,有没有轻量级的测试软件呢?GpuTest就是一款十分小巧的软件,这是一款基于OpenGL的显卡压力测试软件,GpuTest还是一款跨平…

pandas 合并所有列_Python学习:Pandas库

pandas包含数据结构和数据处理工具的设计使得在Python中进行数据清洗和分析非常快捷。pandas经常是和NumPy,Scipy以及数据可视化工具matplotlib一起使用的。pandas支持大部分NumPy语言风格的数组计算,但最大的不同在于pandas是用于处理表格型或异质型数据的。而NumP…

进程和多线程

一、进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ、Xcode,系统就会分别启动2个进程 通过“活动监视器”可以查看Mac系统中所开启的进程 2.什么是线…

CUMT--Java复习--网络编程

目录 一、Java网络API 1、InetAddress类 2、URL类 3、URLConnection类 4、URLDecoder类和URLEncoder类 二、基于TCP的网络编程 1、Socket类 2、ServerSocket类 三、网络通信过程 一、Java网络API Java中有关网络方面的功能都定义在java.net中。 1、InetAddress类 Jav…

iOS懒加载

1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小)。所谓懒加载,写的是其getter方法。说的通俗一点,就是在开发中,当程序中需要利用的资源时。在程序启动的时候不…

【Django】Django Debug Toolbar调试工具配置

正在发愁怎么调试Django,就遇到了Django Debug Toolbar这个利器。 先说遇到的问题: 网上也有教程,不过五花八门的,挨个尝试了一遍,也没有成功运行。最后终于找到问题所在: 从开发服务器日志可知&#xff1a…

python中提取pdf文件某些页_人工智能|Python提取PDF中的文本并朗读

题前的话之前有老师在群里推荐这个,我看了一眼觉得还是蛮有趣的,然后就忘了……昨天又看到这个《宅男福利!我50行Python代码让小姐姐给你读Pdf》,今天于是开始自己尝试,谁知道pdfplumber库怎么也安装不了,最…

[UVA315]Network(tarjan, 求割点)

题目链接:https://uva.onlinejudge.org/index.php?optioncom_onlinejudge&Itemid8&pageshow_problem&problem251 求割点,除了输入用strtok和sscanf处理输入以外,对于求割点的tarjan算法有了进一步理解。 特别注意88行&#xff0…

prim求最短路径C语言,[图论]Prim算法求最小支撑树和最短路径

这个是以前所学,现在总结成博文一篇。对于图论中的求解最小支撑树问题和最短路径问题都有比较经典的算法,比如最小支撑树可以采用“破圈法”,求解最短路径可以用“Dijkstra算法”。这里笔者将回顾下求解最小支撑树的Prim算法和最短路径算法。…

pycharm镜像源_pycharm安装第三方库

点击蓝字关注我们hello,大家好,我是你们的小编大飞。小编一直在学习编程语言,挑选了很久之后决定入了python的坑(bushi)。而python之所以火,是因为它专注于如何解决问题、自由开放的社区环境以及丰富的第三方库。几乎可以这么说&a…

android系统源码的环境下用make来编译,Android源码编译系统入门

做过 Android 平台开发的朋友对make,mm或make clean命令应该很熟悉,但也许大家只是熟知这些命令的作用却不知道这些命令底下有些什么原理?那么今天我就带着大家推开Android编译系统的大门,探索一下这片未知的恐怖之森(问啥要用恐怖…

(mac)阿里云ECS服务器配置过程

-----首先本人是半只脚入门的iOS开发者,弄这个只是单纯想多学点东西。 -----阿里云服务器的配置选择:既然是学习用的,最最基础的配置就行了。1M带宽,1核1G...这就不详述了。没啥可选的,(其中有个创建实例&a…