讲讲 iOS 开发中的 SOLID 原则

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

在软件工程中,SOLID 原则是五个基本原则,旨在促进更好的软件设计:更可维护、更易于理解、更灵活。对于 iOS 开发者来说,掌握和应用这些原则是非常重要的,因为它们可以帮助你构建出高质量的应用程序。今天准备来尝试介绍下我对这些原则的理解,并提供具体的 iOS 开发例子来说明如何在实践中应用这些原则。

单一职责原则 (SRP)

单一职责原则指的是一个类应该只负责一项任务。在 iOS 开发中,遵循此原则可以避免创建庞大的类,每个类都应该专注于单一的功能。

举个例子,比如你有一个个人中心的控制器 UserProfileViewController,它的职责是展示用户的个人信息,而不应该同时负责从网络获取这些信息。这种职责的分离使得代码更易于维护和测试。

less 复制代码
class UserProfileService {
    func fetchUserProfile(completion: @escaping (UserProfile) -> Void) {
        // 实现网络请求获取用户资料
    }
}

如果你的这个页面有网络请求相关的代码,可以考虑创建另一个类,比如 UserProfileService,在这个类中进行页面需要的数据请求,这样我们就使 UserProfileViewController 遵循了单一职责原则,使其变得更加清晰和易于管理。

开放封闭原则 (OCP)

开放封闭原则强调软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。

什么意思呢,一个类一旦设计开发完成,就应该可以独立完成其工作,而不要对类进行任何修改,如果你想要增加功能,应该通过扩展/集成/实现接口等方式。

在 iOS 开发中,这种原则也很常见,比如我要设计一个图像处理功能的协议 ImageFilter,协议一旦设计完成,就不再更改了,假设这个协议只有一个方法 apply(to:) 输入一个图片,返回一个图片。

swift 复制代码
protocol ImageFilter {
    func apply(to image: UIImage) -> UIImage
}

如果此时我想增加一个模糊滤镜的功能,我可以新建一个类来遵守这个协议,并实现 apply(to:) 方法:

swift 复制代码
class BlurFilter: ImageFilter {
    func apply(to image: UIImage) -> UIImage {
        // 应用模糊滤镜...
        return image
    }
}

这样,任何新的滤镜都可以通过实现ImageFilter协议来创建,从而遵循了开放封闭原则。

里氏替换原则 (LSP)

里氏替换原则其实是针对继承而言的,要求子类能够替换其基类,而不破坏程序的正确性。这意味着子类应该完全实现父类的行为。

在现在的编程语言中基本都符合这个原则,在 iOS 开发中也不例外,一个简单的例子,如果我们有一个 Bird 类和一个 FlyingBird 子类,那么任何 FlyingBird 的实例都应该能够替换Bird的实例。

swift 复制代码
class Bird {
    func layEgg() {
        print("Laying an egg.")
    }
}

class FlyingBird: Bird {
    func fly() {
        print("Flying.")
    }
}

通过确保 FlyingBird 遵循 LSP,我们可以确保我们的代码更加灵活和可靠。

接口隔离原则 (ISP)

接口隔离原则指的是客户端不应该依赖它不使用的接口,这其实跟单一职责有点关系,一个大型接口往往有很多功能,但是继承者往往不需要这么多功能,就需要把大型接口拆分为更小、更具体的接口。

例如,你有一个打印机的类,它拥有打印、扫描、复制等功能,我们可以将打印、扫描和复印功能分解为独立的协议,这样,打印机只需要依赖打印功能、扫描仪就只需要依赖扫描功能,或者选择性的依赖多个功能。

swift 复制代码
// 打印功能
protocol Printer {
    func printDocument(document: Document)
}

// 扫描功能
protocol Scanner {
    func scanDocument(document: Document) -> Data
}

// 复印功能
protocol Copier {
    func copyDocument(document: Document) -> Document
}

// 只打印,只需要遵守 Printer 协议
class SimplePrinter: Printer {
    func printDocument(document: Document) {
        
    }
}

// 办公室多功能打印机,需要遵守 Printer, Scanner, Copier 协议
class OfficePrinter: Printer, Scanner, Copier {
    func printDocument(document: Document) {
        // 打印
    }
    
    func scanDocument(document: Document) -> Data {
        // 扫描
        return Data()
    }
    
    func copyDocument(document: Document) -> Document {
        // 复印
        return Document()
    }
}

这样,实现这些协议的类只需要关心它们真正需要的功能,从而使代码更加清晰和灵活。

依赖倒置原则 (DIP)

依赖倒置原则强调高层模块不应该依赖低层模块,两者都应该依赖抽象。

概念还是太抽象了,我们来举个例子帮助理解,比如你有个从网络获取数据的类 NetworkFetcher,和一个从数据库获取数据的类 DatabaseFetcher,然后有个提供数据的工具类 DataProvider 来直接依赖前面两个类,这种做法就违背了依赖倒置原则。

正确的做法是将 NetworkFetcherDatabaseFetcher 抽象出一个新的接口给 DataProvider 依赖,我们可以定义一个 DataFetcher 协议,然后让 NetworkFetcherDatabaseFetcher 类实现这个协议:

less 复制代码
protocol DataFetcher {
    func fetchData(completion: @escaping (Data?) -> Void)
}

class NetworkFetcher: DataFetcher {
    func fetchData(completion: @escaping (Data?) -> Void) {
        // 从网络获取数据
    }
}

class DatabaseFetcher: DataFetcher {
    func fetchData(completion: @escaping (Data?) -> Void) {
        // 从数据库获取数据
    }
}

class DataProvider {
    let fetcher: DataFetcher
    
    init(fetcher: DataFetcher) {
        self.fetcher = fetcher
    }
    
    func fetchData() {
        fetcher.fetchData { data in
            // 使用数据
        }
    }
}

这样,DataProvider 类就可以依赖于 DataFetcher 协议,而不是任何具体的数据获取方式,从而提高了代码的灵活性和可测试性。

结论

遵循 SOLID 原则是构建健壮、可维护和灵活的 iOS 应用程序的关键。通过实际的例子,我们可以看到这些原则如何帮助我们改进设计和架构。虽然有些人(或者初学者)可能会觉得遵循这些原则有些麻烦或者困难,但随着经验的不断积累,你就会越来越能感觉到这些原则的重要性,学习更多编程的哲学,这也是你变成大佬的必经之路。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
goto_w1 小时前
uniapp上使用webview与浏览器交互,支持三端(android、iOS、harmonyos next)
android·vue.js·ios·uni-app·harmonyos
Swift社区15 小时前
Swift LeetCode 246 题解:中心对称数(Strobogrammatic Number)
开发语言·leetcode·swift
iOS阿玮19 小时前
苹果 iOS 19 曝光,你的iPhone 还能再战一年?
app·apple
鸿蒙布道师19 小时前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
刘小哈哈哈20 小时前
封装了一个iOS多分区自适应宽度layout
macos·ios·cocoa
Lexiaoyao2020 小时前
SwiftUI 字体系统详解
swiftui·swift
YungFan20 小时前
Swift 6.1 新特性
swift
布多1 天前
Tagged Pointer:苹果工程师的内存优化艺术
ios·源码
Rudon滨海渔村1 天前
新旧iPhone相册复制 - 相册图片视频对拷 - 换机 - 迁移设备数据 - 免费开源爱思助手
ios·iphone
清晨細雨2 天前
UniApp集成极光推送详细教程
android·ios·uni-app·极光推送