设计模式与软件原则 (一):SOLID 原则

设计模式与软件原则(Design Patterns and Software Principles)

Gang of Four 在其书《设计模式:可重用面向对象软件的要素》(Elements of Reusable Object-Oriented Software)中,将设计模式大致分为三种类型:

  1. Creational - 处理实体创建,例如 Singleton 和 Factory 设计模式。
  2. Structural 结构 - 确定实现实体之间关系的简单方法。例如适配器设计模式。
  3. Behavioural 行为 - 识别实体之间的常见通信模式。例如观察者设计模式。

在某些情况下,委托(Delegation)和扩展(Extensions)通常被称为设计模式,因为它们被用作许多其它设计模式工作的基础。

MVC 和 MVVM 通常也被称为设计模式,但将它们称为架构设计(architectural design)模式通常更正确,这与 Gang of Four 定义的三种设计模式类型不同。其证据可以在使 MVC 出名的书《面向模式的软件架构 (POSA)》(1996 年)中找到,它清楚地将 MVC 确定为一种架构设计模式。

软件原则是一组指导方针,使我们的代码随着规模的增长而更易于维护、测试、理解和管理。软件原则的示例包括 DRY (Do Not Repeat Yourself)(不要重复自己)原则和我们将在这部分课程中学习的 SOLID 原则。

SOLID 设计原则

SOLID 设计原则鼓励我们创建更易于维护、更易于理解和更灵活的软件。

  1. 单一职责原则(Single Responsibility Principle)

实体应承担一项责任。

  1. 开闭原则(Open-Closed Principle)

实体应该对 extension 开放但对修改(modification) 关闭。

  1. 里氏替换原则(Liskov Substitution Principle)

如果类 A 是类 B 的子类型,那么我们应该能够用 A 替换 B 而不会破坏程序的行为。

  1. 接口隔离(Interface Segregation)

实体不应使用他们不会完全使用的接口。大接口应该拆分成更小的接口。

  1. 依赖倒置(Dependency Inversion)

高级模块不应该依赖于低级模块,两者都应该依赖于抽象。

下面我们来看代码示例:

// 一、单一职责原则(Single Responsibility Principle)

class User {
    
    var name: String
    var profileName: String
    
    init(name: String, profileName: String) {
        self.name = name
        self.profileName = profileName
    }
    
    func changeName(to name: String) {
        self.name = name
    }
    
    func changeProfileName(to profileName: String) {
        self.profileName = profileName
    }
    
}

struct Account {
    
    var user: User
    
    init(user: User) {
        self.user = user
    }
    
    func createAccount() {
        print("account created")
    }
    
    func loginAccount() {
        print("logged into account")
    }
    
    func logoutAccount() {
        print("logged out of account")
    }
    
}

//二、开闭原则

class Guitar {
    
    var brandName: String
    var model: String
    
    init(brandName: String, model: String) {
        self.brandName = brandName
        self.model = model
    }
    
}

class FlameGuitar: Guitar {
    var flame: String = "Red"
}

protocol Instrument {
    var brandName: String { get set }
    var model: String { get set }
}

class BassGuitar: Instrument {
    
    var brandName: String
    var model: String
    
    init(brandName: String, model: String) {
        self.brandName = brandName
        self.model = model
    }
    
}

class WaterGuitar: Instrument {
    
    var brandName: String
    var model: String
    var waterVolume: Int
    
    init(brandName: String, model: String, waterVolume: Int) {
        self.brandName = brandName
        self.model = model
        self.waterVolume = waterVolume
    }
    
}

// 三、里氏替换原则(Liskov Substitution Principle)
protocol Polygon {
    var area: Float { get }
}

class Rectangle: Polygon {
    
    var width: Float = 0
    var length: Float = 0
    
    init(length: Float, width: Float) {
        self.length = length
        self.width = width
    }
    
    var area: Float {
        return width * length
    }
    
}

class Square: Polygon {
    
    var side: Float = 0 

    init(side: Float) {
        self.side = side
    }
    
    var area: Float {
        return side * side
    }
    
}

func printArea(ofPolygon polygon: Polygon) {
    print(polygon.area)
}

let rectangle = Rectangle(length: 10, width: 2)
printArea(ofPolygon: rectangle)
let square = Square(side: 2)
printArea(ofPolygon: square)

// 四、接口隔离(Interface Segregation)
protocol Vehicle {
    func accelerate()
}

protocol Engine {
    func turnEngineOn() 
}

class MotorCar: Vehicle, Engine {
    
    func turnEngineOn() {  
        print("engine on!")
    }
    
    func accelerate() {
        print("going faster")
    }
}

class HorseDrawnCarriage: Vehicle {
    func accelerate() {
        print("going faster")
    }
}

// 五、依赖倒置(Dependency Inversion)
protocol CloudService {
    func fetchData(url: String) -> [String]
}

struct FirebaseService: CloudService {
    
    func observeSingleEvent(forRef: String) -> [String] {
        return ["Post"]
    }
    
    func fetchData(url: String) -> [String] {
        return observeSingleEvent(forRef: url)
    }
}

struct ParseService: CloudService {
    
    func fetchData(url: String) -> [String] {
        return ["Post"]
    }
}

class UserFeed {
    
    private let data: CloudService
    
    init(data: CloudService) {
        self.data = data
    }
    
    func getUserFeedData(url: String) {
        data.fetchData(url: url)
    }
}

let parseService = ParseService()
let userFeedService = UserFeed(data: parseService)
userFeedService.getUserFeedData(url: "url")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值