上一篇 設計模式(Swift) - 1.MVC和代理 中涉及到了三點,類圖,MVC和代理模式.git
單例限制了類的實例化,一個類只能實例化一個對象,全部對單例對象的引用都是指向了同一個對象. github
// 定義一個單例
final public class MySingleton {
static let shared = MySingleton()
private init() {} // 私有化構造方法(若是有須要也能夠去掉)
}
// 使用
let s1 = MySingleton.shared
let s2 = MySingleton.shared
// let s3 = MySingleton() // 報錯
dc.address(o: s1) // 0x000060400000e5e0
dc.address(o: s2) // 0x000060400000e5e0
複製代碼
相比OC,swift中單例的實現簡化了很多,swift中可使用let這種方式來保證線程安全.編程
經過備忘錄模式咱們能夠把某個對象保存在本地,並在適當的時候恢復出來. swift
Swift tips: Codable Codable是swift4推出來的新特性,全部基本類型都實現了 Codable 協議,只要自定義的對象遵照了該協議,就能夠保存和恢復所須要的對象. 本質上Codable,就是Decodable和Encodable的集合. 具體拓展能夠看這裏Swift 4 踩坑之 Codable 協議設計模式
public typealias Codable = Decodable & Encodable
複製代碼
我的用戶信息的本地化存儲,包括用戶token啊之類的.安全
// MARK: - Originator(發起人)
public class UserInfo: Codable {
static let shared = UserInfo()
private init() {}
public var isLogin: Bool = false
public var account: String?
public var age: Int?
var description: String {
return "account:\(account ?? "爲空"), age:\(age ?? 0)"
}
}
// MARK: - 備忘錄(Memento): 負責存儲Originator對象,swift中由Codable實現
// MARK: - 管理者(CareTaker)
public class UserInfoTaker {
public static let UserInforKey = "UserInfoKey"
private static let decoder = JSONDecoder()
private static let encoder = JSONEncoder()
private static let userDefaults = UserDefaults.standard
public static func save(_ p: UserInfo) throws {
let data = try encoder.encode(p)
userDefaults.set(data, forKey: UserInforKey)
}
public static func load() throws -> UserInfo {
guard let data = userDefaults.data(forKey: UserInforKey),
let userInfo = try? decoder.decode(UserInfo.self, from: data)
else {
throw Error.UserInfoNotFound
}
// decode生成的對象不是單例對象,須要轉換成單例對象
// 若是你有更好的實現方式歡迎交流
let userInfoS = UserInfo.shared
userInfoS.account = userInfo.account
userInfoS.age = userInfo.age
userInfoS.isLogin = userInfo.isLogin
return userInfoS
}
public enum Error: String, Swift.Error {
case UserInfoNotFound
}
}
複製代碼
let userInfo = UserInfo.shared
userInfo.isLogin = true
userInfo.account = "132154"
userInfo.age = 16
// 保存
do {
try UserInfoTaker.save(userInfo)
}catch {
print(error)
}
// 讀取
do {
let newUserInfo = try UserInfoTaker.load()
dc.log(newUserInfo.description) // account:132154, age:16
dc.address(o: newUserInfo) // 0x000060000009a400
}catch {
print(error)
}
dc.log(userInfo.description) // account:132154, age:16
dc.address(o: userInfo) // 0x000060000009a400
複製代碼
備忘錄的最大好處就是能夠恢復到特定的狀態,但每次的讀寫操做須要消耗必定的系統資源,因此在某些場景下能夠將單例模式和備忘錄模式結合來統一管理操做數據.服務器
在平常開發中,咱們常常會碰到邏輯分支,咱們通常會用 if else或者switch去處理,但其實還有更好的方式: 策略模式. 策略模式抽象並封裝業務細節,只給出相關的策略接口做爲切換. app
實現一個商場打折的例子,分爲三種狀況,原價購買,按照一個折扣購買,滿多少返現多少(滿100減20).框架
能夠先思考下再看代碼.ui
// 策略協議
protocol DiscountStrategy {
// 支付價格
func payment(money: Double) -> Double
}
// 原價購買
class DiscountNormal: DiscountStrategy {
func payment(money: Double) -> Double {
return money
}
}
// 打折
class DiscountRebate: DiscountStrategy {
private let rebate: Double // 折扣
init(rebate: Double) {
self.rebate = rebate
}
func payment(money: Double) -> Double {
return money * rebate/10.0
}
}
// 返現
class DiscountReturn: DiscountStrategy {
private let moneyCondition: Double // 滿
private let moneyReturn: Double // 返
init(moneyCondition: Double, moneyReturn: Double) {
self.moneyCondition = moneyCondition
self.moneyReturn = moneyReturn
}
func payment(money: Double) -> Double {
return money - (Double(Int(money/moneyCondition)) * moneyReturn)
}
}
// 策略枚舉
enum PayMentStyle {
case normal
case rebate(rebate: Double)
case `return`(moneyCondition: Double, moneyReturn: Double)
}
// 策略管理
class DiscountContext {
var discountStrategy: DiscountStrategy?
init(style: PayMentStyle) {
switch style { // 對應的三種方式
case .normal:
discountStrategy = DiscountNormal()
case .rebate(rebate: let money):
discountStrategy = DiscountRebate(rebate: money)
case .return(moneyCondition: let condition, moneyReturn: let `return`):
discountStrategy = DiscountReturn(moneyCondition: condition, moneyReturn: `return`)
}
}
func getResult(money: Double) -> Double {
return discountStrategy?.payment(money: money) ?? 0
}
}
複製代碼
let money: Double = 800
let normalPrice = DiscountContext(style: .normal).getResult(money: money)
let rebatePrice = DiscountContext(style: .rebate(rebate: 8)).getResult(money: money)
let returnPrice = DiscountContext(style: .return(moneyCondition: 100, moneyReturn: 20)).getResult(money: money)
print("正常價格:\(normalPrice)") // 正常價格:800.0
print("打八折:\(rebatePrice)") // 打八折:640.0
print("滿100返20:\(returnPrice)") // 滿100返20:640.0
複製代碼
以上就是一個簡單的策略模式實現,經過DiscountContext來管理每個DiscountStrategy.
主要講了三種模式,只能實例化一個對象的單例模式,能夠存儲和恢復數據的備忘錄模式以及能夠在複雜業務邏輯下替代if else和switch語句的策略模式.
參考:
The Swift Programming Language (Swift 4.1)
若有疑問,歡迎留言 :-D