持续创作,加速成长!这是我参与「掘金日新计划 · 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)
}
复制代码
ZIPModel
、RARModel
、ZModel
三个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文件的解压缩...
文件压解缩成功,已保存至./解压外观模式
复制代码
结语
通过上面的学习,外观模式看起来不算太难,就类似与经常做的二次封装,将常用的几个函数通过外观模式进行封装,这样调用的时候就可以方便迅速。
同样,外观模式也比较适合解耦,再不操作第三方库的情况下,自己增加一些东西,也可以方便开发。
扩展阅读 下面还有其他模式