首页 设计模式:面向对象设计的六大原则
文章
取消

设计模式:面向对象设计的六大原则

本文主要讲的是面向对象设计应该遵循的六大原则,掌握这些原则能帮助我们更好的理解面向对象的概念,也能更好的理解设计模式。这六大原则分别是:

  • 单一职责原则
  • 开闭原则
  • 里式替换原则
  • 接口隔离原则
  • 依赖倒置原则
  • 迪米特原则

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协议,新的形状如CircleSquare可以被添加进系统而不需要改动其他代码。

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如何存储书籍。这样就减少了LibraryPatronBook的依赖,实现了类之间的松耦合。

本文由作者按照 CC BY 4.0 进行授权