设计模式之组合模式
组合模式:组合多个对象形成树形结构以表示具有“整体-部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,它是一种对象结构模式。
组合模式通过一种巧妙的设计方案,可以一致性地处理整个树形结构或树形结构的一部分,也可以一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点),其实就是利用对象的多态性来实现的。
组合模式结构
Component( 抽象构件):它可以是接口或抽象类,为叶子构建和容器构建对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。
Leaf (叶子构件):它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。
Composite (容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现在抽象构件中定义的行为,包括那些访问及管理子构建的方法,在其业务方法中可以递归调用其子节点的业务方法。
例子 文件夹和文件之间的关系,非常适合用组合模式来描述。文件夹既可以包含文件,又可以包含其他文件夹,最终可能组合成一棵树。
当我用杀毒软件扫描该文件夹时,往往不会关心里面有多少文件和子文件夹,组合模式使得我们只需要操作最外层的文件夹进行扫描。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 abstract class Component { name :String ; constructor (name:String ){ this .name = name } public add (f :Component ):void {} public scan ():void {} } class FileLeaf extends Component { public add (f : Component ): void { throw new Error ("不可往文件中添加文件" ) } public scan (): void { console .log (this .name +"--正在被扫描" ) } } class FolderComposite extends Component { files :Component []=[]; public add (f : Component ): void { this .files .push (f) } public scan (): void { console .log (this .name +"-文件夹正在被扫描" ) this .files .forEach (f => { f.scan (); }) } } let folder = new FolderComposite ("父文件夹一" );let folder1 = new FolderComposite ("子文件夹1" );let folder2 = new FolderComposite ("子文件夹2" );let f1 = new FileLeaf ("vue的设计与实现.pdf" )let f2 = new FileLeaf ("avatar.png" )let f3 = new FileLeaf ("总结报告.word" )folder1.add (f1); folder2.add (f2); folder.add (f3); folder.add (folder1); folder.add (folder2); folder.scan ();