本文主要讲的是面向对象设计应该遵循的六大原则,掌握这些原则能帮助我们更好的理解面向对象的概念,也能更好的理解设计模式。这六大原则分别是:
- 单一职责原则
- 开闭原则
- 里式替换原则
- 接口隔离原则
- 依赖倒置原则
- 迪米特原则
1. 单一职责原则 (Single Responsibility Principle, SRP)
单一职责原则指一个类应该只有一个引起它变化的原因。这意味着一个类应该只负责一项任务。
1
2
3
4
5
6
7
8
9
10
11
12
class UserSettings {
func updateEmail(email: String) {
// 更新邮箱地址
}
}
class UserAuthentication {
func login(email: String, password: String) -> Bool {
// 进行登录
return true
}
}
实例中UserSettings
类负责管理用户设置,而UserAuthentication
类负责处理用户认证。每个类只负责一项功能。
2. 开闭原则 (Open/Closed Principle, OCP)
开闭原则表示软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着应该能够在不修改现有代码的情况下扩展其行为。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protocol Shape {
func draw()
}
class Circle: Shape {
func draw() {
// 绘制圆形
}
}
class Square: Shape {
func draw() {
// 绘制正方形
}
}
通过实现Shape
协议,新的形状如Circle
和Square
可以被添加进系统而不需要改动其他代码。
3. 里氏替换原则 (Liskov Substitution Principle, LSP)
里氏替换原则指派生类(子类)对象应该能够替换其基类(超类)对象被使用,而不破坏程序的正确性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Bird {
func fly() {
// 默认的飞行行为
}
}
class Sparrow: Bird {
override func fly() {
// 麻雀特有的飞行行为
}
}
class Ostrich: Bird {
override func fly() {
// 不实现飞行行为,或抛出一个异常
}
}
如果Ostrich
(鸵鸟)继承自Bird
但不实现飞行,这违反了LSP。正确的做法可能是重新设计类的结构,确保替换不会导致错误。
4. 接口隔离原则 (Interface Segregation Principle, ISP)
接口隔离原则指不应该强迫客户程序依赖它们不使用的方法。接口应该被细分,使得类只需要实现它们需要的接口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protocol Printable {
func print()
}
protocol Scanable {
func scan()
}
class Printer: Printable {
func print() {
// 实现打印
}
}
class Scanner: Scanable {
func scan() {
// 实现扫描
}
}
Printer
类只实现了Printable
接口,Scanner
类只实现了Scanable
接口,遵循了ISP原则。
5. 依赖倒置原则 (Dependency Inversion Principle, DIP)
依赖倒置原则指高层模块不应该依赖低层模块,二者都应该依赖于抽象;抽象不应该依赖细节,细节应该依赖抽象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protocol DataStore {
func save(data: String)
}
class CloudStore: DataStore {
func save(data: String) {
// 保存数据到云
}
}
class LocalStore: DataStore {
func save(data: String) {
// 本地保存数据
}
}
class DataManager {
var store: DataStore
init(store: DataStore) {
self.store = store
}
func saveData(data: String) {
store.save(data: data)
}
}
DataManager
依赖于DataStore
抽象而不是具体的数据存储方式,满足DIP原则。
6. 迪米特原则 (Law of Demeter, LoD)
迪米特原则,也称为最少知识原则,建议一个对象应当对其他对象有尽可能少的了解。迪米特原则通过减少对象之间的直接交互来降低系统的整体复杂度,促进了高内聚和低耦合的设计。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Book {
var title: String
init(title: String) {
self.title = title
}
}
class Library {
private var books: [Book] = [Book(title: "Swift Programming"), Book(title: "Design Patterns")]
func getBookTitles() -> [String] {
books.map { $0.title }
}
}
class LibraryPatron {
let library = Library()
func printBookTitles() {
let titles = library.getBookTitles()
for title in titles {
print(title)
}
}
}
在这个例子中,LibraryPatron
不直接与Book
对象交互,而是通过Library
来获取书籍的标题。LibraryPatron
只需要知道Library
提供了getBookTitles
方法,而不需要了解Book
的内部结构或者Library
如何存储书籍。这样就减少了LibraryPatron
对Book
的依赖,实现了类之间的松耦合。