Typescript 组合模式(Composite)

2019-01-07  本文已影响12人  我不叫奇奇

标签: 前端 设计模式 组合模式 typescript composite


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

composite.jpg

组合模式

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

实际场景

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

组合模式的结构

组合模式的例子

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

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);

组合模式的利弊

利:

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

上一篇 下一篇

猜你喜欢

热点阅读