我学会了,组合模式

简介: 组合模式属于结构型模式,这个类型的设计模式总结出了 类、对象组合后的经典结构,将类、对象的结构和使用解耦了,花式的去借用对象。

前言

组合模式属于结构型模式,这个类型的设计模式总结出了 类、对象组合后的经典结构,将类、对象的结构和使用解耦了,花式的去借用对象。

组合模式

使用场景:当你遇到 局部到整体的情况时,比如文件目录与子文件、子目录这样的有层次的树结构,就可以使用组合模式了。

理解:类、对象的结构和使用解耦,通过嵌套的结构让对象与对象之间拥有了层次关系,这种层次关系也支持动态增加或者减少。正常情况下应该使用一个class来实现,其实只需要一个FileNode即可。但是我将FIle和Dir分开了,我觉得需要拆分一下,这样就可以拥有各自互不干扰的行为,但是就目前来看,也造成了冗余代码的产生,不过你应该也发现了 这种结构有缺陷,比如File不应该有子文件,但是我们还是让它拥有了addChild方法,虽然我们直接将它抛异常。

namespace struct_mode_06 {

    interface IFile {

        list: Array<IFile>
        parent?: IFile

        fileName: string
        fileSize: string
        fileType: string
        isDir: boolean

        getPath(): string
        getCount(): number

        // 从下往上
        setParent(parent: IFile): IFile
        
        // 从下往上
        addChild(children: IFile): IFile

    }

    class File implements IFile {
        list: IFile[];
        fileName: string;
        fileSize: string;
        fileType: string;
        isDir: boolean;
        parent?: IFile;

        constructor(fileName: string, fileSize: string, fileType: string, parent?: IFile) {
            this.fileName = fileName
            this.fileSize = fileSize
            this.fileType = fileType
            this.isDir = false

            this.list = new Array()
            if (parent) {
                this.parent = parent
            }
        }

        setParent(parent: IFile): IFile {

            if (!parent.list.includes(this)) {
                parent.list.push(this)
                this.parent = parent
            } else {
                throw new Error("已经有父亲了");
            }

            return this
        }

        addChild(children: IFile): IFile {
            throw new Error("无法追加");
        }

        getPath(): string {
            let parent = this.parent
            let pathStack = [this.fileName]
            while (parent) {
                pathStack.unshift(parent.fileName)
                parent = parent.parent
            }

            return pathStack.join('/');
        }

        getCount(): number {
            return 1
        }
    }

    class Dir implements IFile {
        list: IFile[];
        fileName: string;
        fileSize: string;
        fileType: string;
        isDir: boolean;
        parent?: IFile;

        constructor(fileName: string, fileSize: string, fileType: string, parent?: IFile) {
            this.fileName = fileName
            this.fileSize = fileSize
            this.fileType = fileType
            this.isDir = true

            this.list = new Array()

            if (parent) {
                this.parent = parent
            }
        }
        setParent(parent: IFile): IFile {

            if (!parent.list.includes(this)) {
                parent.list.push(this)
                this.parent = parent
            } else {
                throw new Error("已经有父亲了");
            }

            return this
        }
        addChild(children: IFile): IFile {
            if (!this.list.includes(children)) {
                this.list.push(children)
                children.parent = this
            } else {
                throw new Error("已经有儿子了");
            }

            return this
        }

        getPath(): string {
            let parent = this.parent
            let pathStack = [this.fileName]
            while (parent) {
                pathStack.unshift(parent.fileName)
                parent = parent.parent
            }

            return pathStack.join('/');
        }

        getCount(): number {
            let list = this.list

            const result = getSubCount(list, list.length)

            function getSubCount(ls: Array<IFile>, count: number) {
                ls.filter(item => item.isDir).forEach(item => {
                    count += getSubCount(item.list, item.list.length)
                })

                return count
            }

            return result
        }
    }

    const dir = new Dir('DIR', '0KB', '')
    const dir2 = new Dir('DIR--2', '0KB', '')
    const dir3 = new Dir('DIR---3', '0KB', '')
    const file = new File('test.rar', '9KB', 'rar')
    const file2 = new File('test2.rar', '29KB', 'rar')
    const file3 = new File('test3.rar', '19KB', 'rar')

    dir.addChild(file)
    dir.addChild(dir2)
    dir2.addChild(file2)
    dir2.addChild(dir3)
    dir3.addChild(file3)

    console.log(file3.getPath(), dir.getCount())
}
目录
相关文章
|
2月前
|
设计模式 缓存 算法
C#一分钟浅谈:组合模式与外观模式
【10月更文挑战第15天】本文介绍了面向对象设计模式中的组合模式和外观模式。组合模式通过树形结构表示“部分-整体”的层次关系,适用于文件系统、图形界面等场景;外观模式提供统一接口简化复杂系统的使用,适用于视频播放器等多模块系统。文章详细解释了这两种模式的基本概念、应用场景、实现方式及常见问题和解决方法,帮助读者更好地理解和应用。
43 9
|
7月前
|
存储 安全
结构型 组合模式
结构型 组合模式
33 0
|
设计模式 Java 容器
设计模式~组合模式(composite)-16
目录 (1)优点: (2)缺点: (3)使用场景: (4)注意事项: (5)应用实例 代码
66 0
|
前端开发
关于组合模式我所知道的
关于组合模式我所知道的
58 0
|
存储 设计模式 安全
结构型模式-组合模式
结构型模式-组合模式
94 0
|
安全 Java 容器
结构型:组合模式 Composite
主要内容有: 该模式的介绍,包括: 引子、意图(大白话解释) 类图、时序图(理论规范) 该模式的代码示例:熟悉该模式的代码长什么样子 该模式的优缺点:模式不是万金油,不可以滥用模式 该模式的应用案例:了解它在哪些重要的源码中被使用
168 0
|
存储
享元模式与组合模式(2)
享元模式与组合模式(2)
196 0
享元模式与组合模式(2)
|
设计模式 存储 人工智能
享元模式与组合模式(4)
享元模式与组合模式(4)
110 0
享元模式与组合模式(4)
|
存储
享元模式与组合模式(1)
享元模式与组合模式(1)
150 0
享元模式与组合模式(1)
|
存储 设计模式 Java
享元模式与组合模式(3)
享元模式与组合模式(3)
150 0
享元模式与组合模式(3)