From 5142b952e95d6be1ec125289c808cc672ce397cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=86=A0=E6=9D=B0?= <815712739@qq.com> Date: Mon, 20 Mar 2017 18:45:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Delete=20=E6=A0=91=E5=BD=A2=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E7=9A=84=E5=A4=84=E7=90=86=E2=80=94=E2=80=94=E7=BB=84?= =?UTF-8?q?=E5=90=88=E6=A8=A1=E5=BC=8F=EF=BC=88=E4=B8=80=EF=BC=89.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重复的多余的文件 --- ...17\357\274\210\344\270\200\357\274\211.md" | 161 ------------------ 1 file changed, 161 deletions(-) delete mode 100644 " \346\240\221\345\275\242\347\273\223\346\236\204\347\232\204\345\244\204\347\220\206\342\200\224\342\200\224\347\273\204\345\220\210\346\250\241\345\274\217\357\274\210\344\270\200\357\274\211.md" diff --git "a/ \346\240\221\345\275\242\347\273\223\346\236\204\347\232\204\345\244\204\347\220\206\342\200\224\342\200\224\347\273\204\345\220\210\346\250\241\345\274\217\357\274\210\344\270\200\357\274\211.md" "b/ \346\240\221\345\275\242\347\273\223\346\236\204\347\232\204\345\244\204\347\220\206\342\200\224\342\200\224\347\273\204\345\220\210\346\250\241\345\274\217\357\274\210\344\270\200\357\274\211.md" deleted file mode 100644 index 0376b38..0000000 --- "a/ \346\240\221\345\275\242\347\273\223\346\236\204\347\232\204\345\244\204\347\220\206\342\200\224\342\200\224\347\273\204\345\220\210\346\250\241\345\274\217\357\274\210\344\270\200\357\274\211.md" +++ /dev/null @@ -1,161 +0,0 @@ -# 树形结构的处理——组合模式(一) - -树形结构在软件中随处可见,例如操作系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题,组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点)。下面将学习这种用于处理树形结构的组合模式。 - -11.1 设计杀毒软件的框架结构 - -Sunny软件公司欲开发一个杀毒(AntiVirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现需要提供该杀毒软件的整体框架设计方案。 - -在介绍Sunny公司开发人员提出的初始解决方案之前,我们先来分析一下操作系统中的文件目录结构,例如在Windows操作系统中,存在如图11-1所示目录结构: - -![](http://img.my.csdn.net/uploads/201209/07/1347029262_9910.jpg) - -图11-1 Windows目录结构 - -图11-1可以简化为如图11-2所示树形目录结构: - -![](http://img.my.csdn.net/uploads/201209/07/1347032636_4355.jpg) - -图11-2 树形目录结构示意图 - -我们可以看出,在图11-2中包含文件(灰色节点)和文件夹(白色节点)两类不同的元素,其中在文件夹中可以包含文件,还可以继续包含子文件夹,但是在文件中不能再包含子文件或者子文件夹。在此,我们可以称文件夹为容器(Container),而不同类型的各种文件是其成员,也称为叶子(Leaf),一个文件夹也可以作为另一个更大的文件夹的成员。如果我们现在要对某一个文件夹进行操作,如查找文件,那么需要对指定的文件夹进行遍历,如果存在子文件夹则打开其子文件夹继续遍历,如果是文件则判断之后返回查找结果。 - -Sunny软件公司的开发人员通过分析,决定使用面向对象的方式来实现对文件和文件夹的操作,定义了如下图像文件类ImageFile、文本文件类TextFile和文件夹类Folder: - -``` -//为了突出核心框架代码,我们对杀毒过程的实现进行了大量简化 -import java.util.*; - -//图像文件类 -class ImageFile { - private String name; - - public ImageFile(String name) { - this.name = name; - } - - public void killVirus() { - //简化代码,模拟杀毒 - System.out.println("----对图像文件'" + name + "'进行杀毒"); - } -} - -//文本文件类 -class TextFile { - private String name; - - public TextFile(String name) { - this.name = name; - } - - public void killVirus() { - //简化代码,模拟杀毒 - System.out.println("----对文本文件'" + name + "'进行杀毒"); - } -} - -//文件夹类 -class Folder { - private String name; - //定义集合folderList,用于存储Folder类型的成员 - private ArrayList folderList = new ArrayList(); - //定义集合imageList,用于存储ImageFile类型的成员 - private ArrayList imageList = new ArrayList(); - //定义集合textList,用于存储TextFile类型的成员 - private ArrayList textList = new ArrayList(); - - public Folder(String name) { - this.name = name; - } - - //增加新的Folder类型的成员 - public void addFolder(Folder f) { - folderList.add(f); - } - - //增加新的ImageFile类型的成员 - public void addImageFile(ImageFile image) { - imageList.add(image); - } - - //增加新的TextFile类型的成员 - public void addTextFile(TextFile text) { - textList.add(text); - } - - //需提供三个不同的方法removeFolder()、removeImageFile()和removeTextFile()来删除成员,代码省略 - - //需提供三个不同的方法getChildFolder(int i)、getChildImageFile(int i)和getChildTextFile(int i)来获取成员,代码省略 - - public void killVirus() { - System.out.println("****对文件夹'" + name + "'进行杀毒"); //模拟杀毒 - - //如果是Folder类型的成员,递归调用Folder的killVirus()方法 - for(Object obj : folderList) { - ((Folder)obj).killVirus(); - } - - //如果是ImageFile类型的成员,调用ImageFile的killVirus()方法 - for(Object obj : imageList) { - ((ImageFile)obj).killVirus(); - } - - //如果是TextFile类型的成员,调用TextFile的killVirus()方法 - for(Object obj : textList) { - ((TextFile)obj).killVirus(); - } - } -} -``` - -编写如下客户端测试代码进行测试: - -``` -class Client { - public static void main(String args[]) { - Folder folder1,folder2,folder3; - folder1 = new Folder("Sunny的资料"); - folder2 = new Folder("图像文件"); - folder3 = new Folder("文本文件"); - - ImageFile image1,image2; - image1 = new ImageFile("小龙女.jpg"); - image2 = new ImageFile("张无忌.gif"); - - TextFile text1,text2; - text1 = new TextFile("九阴真经.txt"); - text2 = new TextFile("葵花宝典.doc"); - - folder2.addImageFile(image1); - folder2.addImageFile(image2); - folder3.addTextFile(text1); - folder3.addTextFile(text2); - folder1.addFolder(folder2); - folder1.addFolder(folder3); - - folder1.killVirus(); - } -} -``` - -编译并运行程序,输出结果如下: - -``` -****对文件夹'Sunny的资料'进行杀毒 -****对文件夹'图像文件'进行杀毒 -----对图像文件'小龙女.jpg'进行杀毒 -----对图像文件'张无忌.gif'进行杀毒 -****对文件夹'文本文件'进行杀毒 -----对文本文件'九阴真经.txt'进行杀毒 -----对文本文件'葵花宝典.doc'进行杀毒 -``` - -Sunny公司开发人员“成功”实现了杀毒软件的框架设计,但通过仔细分析,发现该设计方案存在如下问题: - -(1) 文件夹类Folder的设计和实现都非常复杂,需要定义多个集合存储不同类型的成员,而且需要针对不同的成员提供增加、删除和获取等管理和访问成员的方法,存在大量的冗余代码,系统维护较为困难; - -(2) 由于系统没有提供抽象层,客户端代码必须有区别地对待充当容器的文件夹Folder和充当叶子的ImageFile和TextFile,无法统一对它们进行处理; - -(3) 系统的灵活性和可扩展性差,如果需要增加新的类型的叶子和容器都需要对原有代码进行修改,例如如果需要在系统中增加一种新类型的视频文件VideoFile,则必须修改Folder类的源代码,否则无法在文件夹中添加视频文件。 - -面对以上问题,Sunny软件公司的开发人员该如何来解决?这就需要用到本章将要介绍的组合模式,组合模式为处理树形结构提供了一种较为完美的解决方案,它描述了如何将容器和叶子进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器和叶子。 \ No newline at end of file From 21d875689e0892c346df640cb7393847931b395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=86=A0=E6=9D=B0?= <815712739@qq.com> Date: Mon, 20 Mar 2017 18:45:43 +0800 Subject: [PATCH 2/2] =?UTF-8?q?Delete=20=E5=B7=A5=E5=8E=82=E4=B8=89?= =?UTF-8?q?=E5=85=84=E5=BC=9F=E4=B9=8B=E6=8A=BD=E8=B1=A1=E5=B7=A5=E5=8E=82?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=EF=BC=88=E4=BA=94=EF=BC=89.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重复的多余的文件 --- ...17\357\274\210\344\272\224\357\274\211.md" | 48 ------------------- 1 file changed, 48 deletions(-) delete mode 100644 " \345\267\245\345\216\202\344\270\211\345\205\204\345\274\237\344\271\213\346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217\357\274\210\344\272\224\357\274\211.md" diff --git "a/ \345\267\245\345\216\202\344\270\211\345\205\204\345\274\237\344\271\213\346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217\357\274\210\344\272\224\357\274\211.md" "b/ \345\267\245\345\216\202\344\270\211\345\205\204\345\274\237\344\271\213\346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217\357\274\210\344\272\224\357\274\211.md" deleted file mode 100644 index eeb788a..0000000 --- "a/ \345\267\245\345\216\202\344\270\211\345\205\204\345\274\237\344\271\213\346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217\357\274\210\344\272\224\357\274\211.md" +++ /dev/null @@ -1,48 +0,0 @@ -# 工厂三兄弟之抽象工厂模式(五) - -5 “开闭原则”的倾斜性 - -Sunny公司使用抽象工厂模式设计了界面皮肤库,该皮肤库可以较为方便地增加新的皮肤,但是现在遇到一个非常严重的问题:由于设计时考虑不全面,忘记为单选按钮(RadioButton)提供不同皮肤的风格化显示,导致无论选择哪种皮肤,单选按钮都显得那么“格格不入”。Sunny公司的设计人员决定向系统中增加单选按钮,但是发现原有系统居然不能够在符合“开闭原则”的前提下增加新的组件,原因是抽象工厂SkinFactory中根本没有提供创建单选按钮的方法,如果需要增加单选按钮,首先需要修改抽象工厂接口SkinFactory,在其中新增声明创建单选按钮的方法,然后逐个修改具体工厂类,增加相应方法以实现在不同的皮肤中创建单选按钮,此外还需要修改客户端,否则单选按钮无法应用于现有系统。 - -怎么办?答案是抽象工厂模式无法解决该问题,这也是抽象工厂模式最大的缺点。在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,抽象工厂模式的这种性质称为“开闭原则”的倾斜性。“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面: - -(1) 增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了“开闭原则”,只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。 - -(2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了“开闭原则”。 - -正因为抽象工厂模式存在“开闭原则”的倾斜性,它以一种倾斜的方式来满足“开闭原则”,为增加新产品族提供方便,但不能为增加新产品结构提供这样的方便,因此要求设计人员在设计之初就能够全面考虑,不会在设计完成之后向系统中增加新的产品等级结构,也不会删除已有的产品等级结构,否则将会导致系统出现较大的修改,为后续维护工作带来诸多麻烦。 - -6 抽象工厂模式总结 - -抽象工厂模式是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用,尤其是在一些框架和API类库的设计中,例如在Java语言的AWT(抽象窗口工具包)中就使用了抽象工厂模式,它使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。抽象工厂模式也是在软件开发中最常用的设计模式之一。 - -1. 主要优点 - -抽象工厂模式的主要优点如下: - -(1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。 - -(2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。 - -(3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。 - -2. 主要缺点 - -抽象工厂模式的主要缺点如下: - -增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。 - -3. 适用场景 - -在以下情况下可以考虑使用抽象工厂模式: - -(1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。 - -(2) 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。 - -(3) 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类型。 - -(4) 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。 - -练习 -> Sunny软件公司欲推出一款新的手机游戏软件,该软件能够支持Symbian、Android和Windows Mobile等多个智能手机操作系统平台,针对不同的手机操作系统,该游戏软件提供了不同的游戏操作控制(OperationController)类和游戏界面控制(InterfaceController)类,并提供相应的工厂类来封装这些类的初始化过程。软件要求具有较好的扩展性以支持新的操作系统平台,为了满足上述需求,试采用抽象工厂模式对其进行设计。