SOLID 原则
一、SOLID 原则总览
SOLID 原则是面向对象设计(OOP)的五大核心设计原则,由 Robert C. Martin(“Uncle Bob”)提出,用于指导我们编写高内聚、低耦合、可维护、可扩展的代码。
SOLID 分别代表:
- S:Single Responsibility Principle(单一职责原则)
- O:Open/Closed Principle(开闭原则)
- L:Liskov Substitution Principle(里氏替换原则)
- I:Interface Segregation Principle(接口隔离原则)
- D:Dependency Inversion Principle(依赖倒置原则)
二、Single Responsibility Principle(单一职责原则)
问题:
什么是单一职责原则?在 iOS 项目中如何体现?
答案:
定义:
一个类应该只有一个引起它变化的原因。也就是说,每个类、结构体或模块都应该只负责一件事。
在 iOS 中的体现:
- ViewController 不应同时负责网络请求、业务逻辑、UI 更新。
- 可通过 MVVM / MVP 等架构将视图逻辑与业务逻辑分离。
- 例如:
class UserViewModel {
func fetchUserInfo() { ... } // 网络请求
}
class UserViewController: UIViewController {
let viewModel = UserViewModel()
override func viewDidLoad() {
super.viewDidLoad()
viewModel.fetchUserInfo()
}
}好处:
- 降低代码复杂度,提升可维护性。
- 单元测试更容易。
三、Open/Closed Principle(开闭原则)
问题:
什么是开闭原则?Swift 中如何实现?
答案:
定义:
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
意思是当需求变化时,应通过“扩展”而不是“修改”原有代码实现新功能。
在 Swift 中常见实现方式:
- 利用 protocol + extension 实现扩展行为。
- 使用 多态(继承或协议实现)。
示例:
protocol Payment {
func pay(amount: Double)
}
class ApplePay: Payment {
func pay(amount: Double) { print("ApplePay: \(amount)") }
}
class PayPal: Payment {
func pay(amount: Double) { print("PayPal: \(amount)") }
}
class PaymentProcessor {
func process(payment: Payment, amount: Double) {
payment.pay(amount: amount)
}
}新增支付方式时,无需修改 PaymentProcessor,只需新增类实现 Payment。
四、Liskov Substitution Principle(里氏替换原则)
问题:
什么是里氏替换原则?违反它会带来什么问题?
答案:
定义:
子类对象必须能够替换父类对象,而不影响程序正确性。
换句话说,子类应当遵守父类的契约,不应削弱父类功能。
示例(违反 LSP):
class Bird {
func fly() { print("Flying") }
}
class Penguin: Bird {
override func fly() { fatalError("Penguins can't fly") } // ❌
}Penguin 无法替代 Bird 使用,会破坏里氏替换原则。
正确做法:
将会飞与不会飞的行为抽象为协议:
protocol Flyable { func fly() }
class Sparrow: Flyable { func fly() { print("Flying") } }
class Penguin { }五、Interface Segregation Principle(接口隔离原则)
问题:
什么是接口隔离原则?在 Swift 中如何体现?
答案:
定义:
客户端不应被迫依赖它不使用的接口。
一个大的接口应被拆分成多个小接口,让实现类只需关心自己需要的部分。
示例:
protocol Worker {
func work()
func eat()
}
class Human: Worker {
func work() { print("Coding") }
func eat() { print("Eating") }
}
class Robot: Worker {
func work() { print("Working") }
func eat() { fatalError("Robots don’t eat!") } // ❌
}改进后:
protocol Workable { func work() }
protocol Eatable { func eat() }
class Human: Workable, Eatable { ... }
class Robot: Workable { ... }这样各类只实现所需的接口。
六、Dependency Inversion Principle(依赖倒置原则)
问题:
什么是依赖倒置原则?在 Swift 开发中如何实践?
答案:
定义:
高层模块不应依赖低层模块,两者都应依赖于抽象(接口)。
换句话说,要依赖抽象而不是具体实现。
示例:
protocol NetworkService {
func fetchData() -> String
}
class APIService: NetworkService {
func fetchData() -> String { return "Data from API" }
}
class ViewModel {
private let service: NetworkService
init(service: NetworkService) {
self.service = service
}
func loadData() {
print(service.fetchData())
}
}ViewModel 只依赖 NetworkService 协议,而不依赖具体实现 APIService,便于测试与扩展。
七、综合应用与面试思路
在 iOS 面试中,面试官常考察:
- 对 SOLID 原则的理解是否能落实到架构(MVC/MVVM/VIPER 等)。
- 是否能通过 协议、泛型、依赖注入(DI) 实现可扩展设计。
- 是否能识别违反原则的反例(如 Massive ViewController)。
答题建议:
- 先简明说出定义。
- 再结合 Swift 举例。
- 最后说明实际项目中的好处。
确认总结:
SOLID 原则是 iOS 架构设计的思想根基。掌握并灵活运用它们,能让代码更健壮、更易测试、更易扩展。