聊聊Swift中的设计模式---结构型(外观模式)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情


前言

在面向对象的开发过程中,其实咱们或多或少的都接触过一些设计模式,可能知道或不知道其对应的名称,也不知道其具体使用场景,今天咱们就来说说几种常见的设计模式,帮助你们在开发过程中,更加得心应手。

正文

外观模式

问题:假如你必须在代码中使用某个复杂的库或框架中的众多对象。 正常情况下, 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确的顺序执行方法等。最终, 程序中类的业务逻辑将与第三方类的实现细节紧密耦合, 使得理解和维护代码的工作很难进行。

解决方案:外观模式

用简单的话说,外观模式就是将多个复杂的接口或函数合并成一个,使得使用的时候更加方便,就像二次封装一样,将常用的几个函数封装在一起,使用的时候直接调合并后的函数就行。

外观模式带来的问题也比较明显,就是通过外观模式包装后的接口,在遇到特殊情况时也不适用,比较不灵活。可能需要另外再进行一个外观模式的包装。

下面咱们来通过一个例子来看看

假设我们有一个压缩与解压缩系统专门处理文件的压缩和解压缩,这个系统有三个模块:ZIPModel、RARModel、ZModel,分别处理 ZIP、RAR、7Z 三种文件格式的压缩与解压缩。现在这一系统要提供给上层应用程序使用。

首先定义一个typealias ModelZipPath自定义传参 ,然后写一个协议,里面定义了压缩和解压缩的函数。

import Foundation

typealias ModelZipPath = (srcFilePath: String, dstFilePath: String)

protocol Model {
    func compress(path: ModelZipPath)
    func decompress(path: ModelZipPath)
}
复制代码

ZIPModelRARModelZModel三个model都遵守Model协议,然后分别实现压缩和解压缩的方法


class ZIPModel: Model {
    func compress(path: ModelZipPath) {
        print("ZIP 模块正在进行(path.srcFilePath)文件的压缩...")
        print("文件压缩成功,已保存至(path.dstFilePath)")
    }

    func decompress(path: ModelZipPath) {
        print("ZIP 模块正在进行(path.srcFilePath)文件的解压缩...")
        print("文件压解缩成功,已保存至(path.dstFilePath)")
    }
}

class RARModel: Model {
    func compress(path: ModelZipPath) {
        print("RAR 模块正在进行(path.srcFilePath)文件的压缩...")
        print("文件压缩成功,已保存至(path.dstFilePath)")
    }

    func decompress(path: ModelZipPath) {
        print("RAR 模块正在进行(path.srcFilePath)文件的解压缩...")
        print("文件压解缩成功,已保存至(path.dstFilePath)")
    }
}

class ZModel: Model {
    func compress(path: ModelZipPath) {
        print("7Z 模块正在进行(path.srcFilePath)文件的压缩...")
        print("文件压缩成功,已保存至(path.dstFilePath)")
    }

    func decompress(path: ModelZipPath) {
        print("7Z 模块正在进行(path.srcFilePath)文件的解压缩...")
        print("文件压解缩成功,已保存至(path.dstFilePath)")
    }
}


复制代码

正常情况下,到这一步就直接实例化对应的model,然后实现压缩或解压缩的方法就行,但是外观模式则再进行一次封装,将这三个model合并,传入对应的参数,就可以进行指定的压缩方式。

压缩系统的外观模式

class CompressionFacade {
    lazy var zipModel = ZIPModel()
    lazy var rarModel = RARModel()
    lazy var zModel = ZModel()

    /// 根据不同的压缩类型,压缩成不同的格式
    func compress(path: ModelZipPath, type: String) -> Bool {

        let extName = "." + type
        let fullName = path.dstFilePath + extName

        if type.lowercased() == "zip" {
            zipModel.compress(path: (path.srcFilePath, fullName))
        } else if type.lowercased() == "rar" {
            rarModel.compress(path: (path.srcFilePath, fullName))
        } else if type.lowercased() == "7z" {
            zModel.compress(path: (path.srcFilePath, fullName))
        } else {
            print("不支持压缩类型(type)")
            return false
        }
        return true
    }

    func decompress(path: ModelZipPath) -> Bool {
        let url = URL(fileURLWithPath: path.srcFilePath)
        let type = url.pathExtension

        if type.lowercased() == "zip" {
            zipModel.decompress(path: path)
        } else if type.lowercased() == "rar" {
            rarModel.decompress(path: path)
        } else if type.lowercased() == "7z" {
            zModel.decompress(path: path)
        } else {
            print("不支持压缩类型(type)")
            return false
        }
        return true
    }
}

复制代码

压缩系统的外观模式就完成了,根据传入不同的type进行对应的压缩或解压缩

接下来看看效果


let facade = CompressionFacade()
facade.compress(path: ("./压缩外观模式.md", "./压缩外观模式"), type: "zip")
facade.decompress(path: ("./解压外观模式.zip", "./解压外观模式"))

print("\n")
facade.compress(path: ("./压缩外观模式.pdf", "./压缩外观模式"), type: "rar")
facade.decompress(path: ("./解压外观模式.rar", "./解压外观模式"))

print("\n")
facade.compress(path: ("./压缩外观模式.odc", "./压缩外观模式"), type: "7z")
facade.decompress(path: ("./解压外观模式.7z", "./解压外观模式"))
复制代码

输出

文件压缩成功,已保存至./压缩外观模式.zip
ZIP 模块正在进行./解压外观模式.zip文件的解压缩...
文件压解缩成功,已保存至./解压外观模式


RAR 模块正在进行./压缩外观模式.pdf文件的压缩...
文件压缩成功,已保存至./压缩外观模式.rar
RAR 模块正在进行./解压外观模式.rar文件的解压缩...
文件压解缩成功,已保存至./解压外观模式


7Z 模块正在进行./压缩外观模式.odc文件的压缩...
文件压缩成功,已保存至./压缩外观模式.7z
7Z 模块正在进行./解压外观模式.7z文件的解压缩...
文件压解缩成功,已保存至./解压外观模式
复制代码

结语

通过上面的学习,外观模式看起来不算太难,就类似与经常做的二次封装,将常用的几个函数通过外观模式进行封装,这样调用的时候就可以方便迅速。

同样,外观模式也比较适合解耦,再不操作第三方库的情况下,自己增加一些东西,也可以方便开发。


扩展阅读 下面还有其他模式

创建型-工厂模式

创建型-建造者模式

结构型-适配器模式

结构型-桥接模式

结构型-组合模式

结构型-装饰器模式

猜你喜欢

转载自juejin.im/post/7108900078919614471