Typescript 组合模式(Composite)


请仔细阅读下面代码,理解其中的设计理念。

 
composite.jpg

组合模式

组合模式: 将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

实际场景

为了方便我们对多个文件的管理,我们引入了“文件夹-文件”的模式。将具有统一性质的文件放入一个文件夹中,将具有统一性质的文件夹再放入另一个文件夹中。可以对整个文件夹系统进行文件的搜索,也可以对某一个文件夹进行搜索。让文件管理变得简单。
而“文件夹-文件”这种结构就是典型 的组合模式。

组合模式的结构

  • Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
  • Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
  • Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

组合模式的例子

现在要实现一个文件夹文件树

Node枚举

/* node-type-enum.ts */ enum NodeTypeEnum { ImageFile = 'image', TextFile = 'text', Folder = 'folder', } export { NodeTypeEnum } 

Node抽象类

/* abstract-node.ts */ import { NodeTypeEnum } from './node-type-enum'; export abstract class AbstractNode { protected name: string; protected type: NodeTypeEnum; protected children: AbstractNode[]; public abstract add(node: AbstractNode): AbstractNode; public abstract getFileDeep(name: string): AbstractNode; } 

文件和文件夹基础类

/* basic-file-folder.ts */ import { AbstractNode } from './abstract-node'; import { NodeTypeEnum } from './node-type-enum'; export abstract class BasicFile extends AbstractNode { public add (file: BasicFile): BasicFile { console.error('文件类型不支持添加'); return this; } public getFileDeep (name: string): BasicFile { if (name === this.name) { return this; } return null; } } export abstract class BasicFolder extends AbstractNode { protected constructor () { super(); this.type = NodeTypeEnum.Folder; this.children = []; } public add (file: AbstractNode): BasicFolder { this.children.push(file); return this; } public getFileDeep (name: string): AbstractNode { if (this.name === name) { return this; } for (let index = 0; index < this.children.length; index++) { const node = this.children[index].getFileDeep(name); if (node) { return node; } } return null; } } 

文件类

/* files.ts */ import { BasicFile } from './basic-file-folder'; import { NodeTypeEnum } from './node-type-enum'; export class ImageFile extends BasicFile { constructor (name: string) { super(); this.name = name; this.type = NodeTypeEnum.ImageFile; } } export class TextFile extends BasicFile { constructor (name: string) { super(); this.name = name; this.type = NodeTypeEnum.TextFile; } } 

文件夹类

/* folder.ts */ import { BasicFolder } from './basic-file-folder'; export default class SystemFolder extends BasicFolder{ constructor(name){ super(); this.name = name; } } 

客户端

/* client.ts */ import { ImageFile, TextFile } from './files'; import SystemFolder from './folder'; export default class Client { public static initTree (): SystemFolder { const folder1: SystemFolder = new SystemFolder('根文件夹'); const folder2: SystemFolder = new SystemFolder('图像文件夹'); const folder3: SystemFolder = new SystemFolder('文本文件夹'); const image1: ImageFile = new ImageFile('a.jpg'); const image2: ImageFile = new ImageFile('b.jpg'); const text1: TextFile = new TextFile('a.txt'); const text2: TextFile = new TextFile('b.txt'); folder2.add(image1).add(image2); folder3.add(text1).add(text2); folder1.add(folder2).add(folder3); return folder1; } } const tree = Client.initTree(); const aJpg = tree.getFileDeep('a.jpg'); console.log(aJpg); 

组合模式的利弊

利:

  • 减少大量手工遍历数组或其他数据的粘合性代码
  • 组合模式中各个对象耦合非常松散,更容易改变他们或互换位置,有利于代码重构
  • 让代码有一个出色的层次体系,客户端调用更方便

弊:
组合模式掩盖了他所支持的每一种操作的代价。如果层次体系很大的话,系统的性能将会收到影响。



作者:我不叫奇奇
链接:https://www.jianshu.com/p/1f8c6ebaf6b6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM