設(shè)計(jì)模式-行為型

設(shè)計(jì)模式-行為型

行為型設(shè)計(jì)模式主要用于軟件運(yùn)行時(shí)復(fù)雜的流程控制坟募。包含:模板方法模式岛蚤、策略模式、命令模式懈糯、職責(zé)鏈模式涤妒、狀態(tài)模式、觀察者模式赚哗、中介者模式她紫、迭代器模式、訪問(wèn)者模式屿储、備忘錄模式和解釋器模式

模板方法模式

在軟件設(shè)計(jì)時(shí)贿讹,很多時(shí)候系統(tǒng)的運(yùn)行流程都是確定的,在整個(gè)流程中够掠,可能只有部分環(huán)節(jié)的具體實(shí)現(xiàn)是有差別的民褂,這時(shí)我們就可以使用模板方法模式,其具體定義為:定義一個(gè)操作流程中的算法骨架祖屏,將部分算法環(huán)節(jié)的實(shí)現(xiàn)延遲到子類中助赞,使子類可以在不改變算法骨架的前提下對(duì)特定步驟進(jìn)行定制。

以職員的工作流程為例:

class Management {
    func clockIn() {
        print("上班")
    }
    func working() {
        print("工作")
    }
    func clockOut() {
        print("下班")
    }
    func start() {
        clockIn()
        working()
        clockOut()
    }
}

無(wú)論對(duì)于任何崗位的職員袁勺,這個(gè)流程都不變雹食,對(duì)于不同的崗位不同的是具體的工作內(nèi)容,例如添加一位工程師期丰,以模板方法模式設(shè)計(jì):

重構(gòu)后

...
class Engineer: Management {
    override func working() {
        print("軟件設(shè)計(jì)")
    }
}

使用模板方法模式設(shè)計(jì)后群叶,代碼的復(fù)用性更強(qiáng)吃挑,但是因?yàn)樽宇愋薷牧烁割惖姆椒ǖ膶?shí)現(xiàn),有悖里氏替換原則街立,因此在選擇時(shí)需要根據(jù)具體場(chǎng)景進(jìn)行分析舶衬。

策略模式

策略模式核心原則是定義一系列算法,將每個(gè)算法獨(dú)立封裝赎离,使用者可以靈活的進(jìn)行選擇替換逛犹。

例如現(xiàn)實(shí)生活中到某地的出行方式有很多種,可以靈活選擇:出租車梁剔、公交車虽画、地鐵、自行車等荣病,需要根據(jù)路程遠(yuǎn)近和交通狀況靈活的選擇码撰,這就是一種策略模式。

重構(gòu)后

protocol Transport {
    func toDestination()
}
class Taxi: Transport {
    func toDestination() {
        print("出租車")
    }
}
class Bus: Transport {
    func toDestination() {
        print("公交車")
    }
}
class Subway: Transport {
    func toDestination() {
        print("地鐵")
    }
}
class Action {
    var destination: String
    var transport: Transport
    init(destination: String, transport: Transport) {
        self.destination = destination
        self.transport = transport
    }
    func go() {
        self.transport.toDestination()
    }
}
let action = Action(destination: "北京", transport: Subway())
action.go()

通過(guò)策略模式个盆,不同的Action對(duì)象調(diào)用go方法很容易根據(jù)場(chǎng)景實(shí)現(xiàn)不同的行為脖岛。

命令模式

命令模式的核心是將請(qǐng)求封裝為對(duì)象,使得請(qǐng)求的發(fā)起與執(zhí)行分開(kāi)颊亮,發(fā)起方和執(zhí)行方通過(guò)命令進(jìn)行交互柴梆。
以教務(wù)系統(tǒng)為例,

struct Teacher {
    var name: String
    var subject: String
    func log() {
        print("\(name) + \(subject)")
    }
}
class School {
    var teachers = [Teacher]()
    func addTeacher(name: String, subject: String) {
        teachers.append(Teacher(name: name, subject: subject))
    }
    func deleteTeacher(name: String) {
        teachers = teachers.filter {$0.name != name}
    }
    func show() {
        for teacher in teachers {
            teacher.log()
        }
    }
}
let school = School()
school.addTeacher(name: "學(xué)偉", subject: "計(jì)算機(jī)")
school.addTeacher(name: "張三", subject: "體育")
school.addTeacher(name: "李四", subject: "數(shù)學(xué)")
school.show()
school.deleteTeacher(name: "李四")
school.show()

其中编兄,School 提供了展示所有教師信息的方法轩性,也提供了添加和刪除教師的方法,通過(guò)這種方式對(duì)教師的操作難以維護(hù)狠鸳,可以使用命令模式對(duì)其重構(gòu),將添加和刪除教師悯嗓、展示所有教師的邏輯都封裝成一種命令件舵。

重構(gòu)后

struct Teacher {
    var name: String
    var subject: String
    func log() {
        print("\(name) + \(subject)")
    }
}
class SchoolCommand {
    enum ActionType {
        case add
        case delete
        case show
    }
    var type: ActionType
    var name: String?
    var subject: String?
    init(type: ActionType, name: String? = nil, subject: String? = nil) {
        self.type = type
        self.name = name
        self.subject = subject
    }
}
class School {
    var teachers = [Teacher]()
    func runCommand(command: SchoolCommand) {
        switch command.type {
        case .add:
            addTeacher(name: command.name!, subject: command.subject!)
        case .delete:
            deleteTeacher(name: command.name!)
        case .show:
            show()
        }
    }
    private func addTeacher(name: String, subject: String) {
        teachers.append(Teacher(name: name, subject: subject))
    }
    private func deleteTeacher(name: String) {
        teachers = teachers.filter {$0.name != name}
    }
    private func show() {
        for teacher in teachers {
            teacher.log()
        }
    }
}
let school = School()
school.runCommand(command: SchoolCommand(type: .add, name: "學(xué)偉", subject: "計(jì)算機(jī)"))
school.runCommand(command: SchoolCommand(type: .add, name: "張三", subject: "體育"))
school.runCommand(command: SchoolCommand(type: .add, name: "李四", subject: "數(shù)學(xué)"))
school.runCommand(command: SchoolCommand(type: .show))
school.runCommand(command: SchoolCommand(type: .delete,name: "李四"))
school.runCommand(command: SchoolCommand(type: .show))

使用命令模式重構(gòu)后,對(duì)于 School 的操作都通過(guò) 命令 SchoolCommand 觸發(fā)脯厨,代碼擴(kuò)展性更強(qiáng)铅祸,且命令可以作為對(duì)象直接被存儲(chǔ)、傳輸合武、重復(fù)和撤銷临梗,在某些場(chǎng)景下會(huì)非常有用。

職責(zé)鏈模式

一個(gè)請(qǐng)求被發(fā)出稼跳,從低層向高層依次尋找可以處理此請(qǐng)求的對(duì)象盟庞,直到找到處理者才結(jié)束責(zé)任鏈。

重構(gòu)后

struct Requet {
    enum Level {
        case low
        case middle
        case high
    }
    var level: Level
}
protocol Handler {
    var nextHandler: Handler? { get }
    func handlerRequest(request: Requet)
    func nextHanderDo(request: Requet)
}
extension Handler {
    func nextHanderDo(request: Requet) {
        if let nextHandler = nextHandler {
            nextHandler.handlerRequest(request: request)
        } else {
            print("無(wú)法處理請(qǐng)求")
        }
    }
}
class HighHandler: Handler {
    var nextHandler: Handler? = nil
    func handlerRequest(request: Requet) {
        if request.level == .high {
            print("HighHandler 處理請(qǐng)求")
        } else {
            nextHanderDo(request: request)
        }
    }
}
class MiddleHandler: Handler {
    var nextHandler: Handler? = HighHandler()
    func handlerRequest(request: Requet) {
        if request.level == .middle {
            print("MiddleHandler 處理請(qǐng)求")
        } else {
            nextHanderDo(request: request)
        }
    }
}
class LowHandler: Handler {
    var nextHandler: Handler? = MiddleHandler()
    func handlerRequest(request: Requet) {
        if request.level == .low {
            print("LowHandler 處理請(qǐng)求")
        } else {
            nextHanderDo(request: request)
        }
    }
}
class Chain: Handler {
    var nextHandler: Handler? = LowHandler()
    func handlerRequest(request: Requet) {
        nextHandler?.handlerRequest(request: request)
    }
}
var request = Requet(level: .low)
Chain().handlerRequest(request: request)
request = Requet(level: .middle)
Chain().handlerRequest(request: request)
request = Requet(level: .high)
Chain().handlerRequest(request: request)

外界只需傳入指定等級(jí)的請(qǐng)求汤善,責(zé)任鏈內(nèi)部即可根據(jù)等級(jí)選擇相應(yīng)的處理邏輯什猖。

責(zé)任鏈模式的核心是將請(qǐng)求發(fā)送到責(zé)任鏈上,鏈上的每一個(gè)處理者可以根據(jù)實(shí)際情況決定是否處理此請(qǐng)求不狮,如果不能處理則將請(qǐng)求繼續(xù)向上發(fā)送,直到被某個(gè)處理者處理或者沒(méi)有處理者為止雾家。這種結(jié)構(gòu)可以靈活地向責(zé)任鏈中增加或刪除處理者铃彰,對(duì)于不同種類的請(qǐng)求,發(fā)出方只需要將其發(fā)送到責(zé)任鏈上芯咧,不需要關(guān)心具體被哪一個(gè)處理者處理牙捉。降低了對(duì)象間的耦合性,并且使責(zé)任的分擔(dān)更加清晰敬飒。

狀態(tài)模式

狀態(tài)模式的核心是:當(dāng)控制一個(gè)對(duì)象行為的狀態(tài)轉(zhuǎn)換過(guò)于復(fù)雜時(shí)邪铲,把狀態(tài)處理的邏輯分離出到單獨(dú)的狀態(tài)類中。
在軟件設(shè)計(jì)中无拗,對(duì)象在不同的情況下會(huì)表現(xiàn)出不同的行為带到,被稱為有狀態(tài)的對(duì)象。影響對(duì)象行為的屬性被稱為狀態(tài)英染,影響對(duì)象行為的屬性被稱為狀態(tài)揽惹。對(duì)有狀態(tài)的對(duì)象進(jìn)行編程時(shí),使用狀態(tài)設(shè)計(jì)模式可以使代碼的內(nèi)聚性更強(qiáng)四康。

重構(gòu)后

class StateContent {
    var currentState: State
    init(_ currentState: State) {
        self.currentState = currentState
    }
    func changeState(curState: State) {
        self.currentState = curState
    }
}
protocol State {
    func info()
    func doAction(content: StateContent)
}
class Open: State {
    func info() {
        print("開(kāi)燈")
    }
    func doAction(content: StateContent) {
        content.currentState = Open()
    }
}
class Close: State {
    func info() {
        print("關(guān)燈")
    }
    func doAction(content: StateContent) {
        content.currentState = Close()
    }
}
class LightButton {
    var stateContent: StateContent
    init(state: State) {
        self.stateContent = StateContent(state)
    }
    func change(state: State) {
        self.stateContent.changeState(curState: state)
    }
    func log() {
        stateContent.currentState.info()
    }
}
let light = LightButton(state: Close())
light.log()
light.change(state: Open())
light.log()

其中 StateContent 定義了狀態(tài)的上下文搪搏,用來(lái)維護(hù)當(dāng)前開(kāi)關(guān)的狀態(tài)。而 Open 闪金、Close 則是對(duì)狀態(tài)的封裝疯溺。

觀察者模式

觀察者模式又被稱為發(fā)布-訂閱模式,在觀察者模式中哎垦,一個(gè)對(duì)象發(fā)生變化會(huì)通知到所有依賴它的對(duì)象囱嫩,依賴它的對(duì)象可以根據(jù)情況進(jìn)行自身行為的更改。
在iOS開(kāi)發(fā)中漏设,通知中心和鍵值監(jiān)聽(tīng)系統(tǒng)的實(shí)現(xiàn)都使用了觀察者模式墨闲。如下代碼通過(guò)實(shí)現(xiàn)一個(gè)簡(jiǎn)易的通知中心演示觀察者模式

重構(gòu)后

typealias XWNotificationCallback = (XWNotification) -> Void
struct XWNotification {
    var name: String
    var data: String
    var object: AnyObject?
    func info() {
        print("name: \(name), data: \(data), object: \(String(describing: object))")
    }
}
struct XWObsever {
    var object: AnyObject
    var callback: XWNotificationCallback
}
class XWNotificationCenter {
    static let shared = XWNotificationCenter()
    private var observers = Dictionary<String, Array<XWObsever>>()
    private init() {}
    func addObserver(name: String, object: AnyObject, callback: @escaping XWNotificationCallback) {
        let observer = XWObsever(object: object, callback: callback)
        if var curObserver = observers[name] {
            curObserver.append(observer)
        } else {
            observers[name] = [observer]
        }
    }
    func removeObserver(name: String) {
        observers.removeValue(forKey: name)
    }
    func postNotification(notification: XWNotification) {
        if let array = observers[notification.name] {
            var postNotification = notification
            for observer in array {
                postNotification.object = observer.object
                observer.callback(postNotification)
            }
        }
    }
}
let key = "KEY"
XWNotificationCenter.shared.addObserver(name: key, object: "監(jiān)聽(tīng)者A" as AnyObject) { noti in
    noti.info()
}
//XWNotificationCenter.shared.removeObserver(name: key)
XWNotificationCenter.shared.postNotification(notification: XWNotification(name: key, data: "通知內(nèi)容"))

以上就是一個(gè)簡(jiǎn)易通知中心的實(shí)現(xiàn),當(dāng)添加了監(jiān)聽(tīng)之后愿题,一旦通知被發(fā)出损俭,回調(diào)方法就會(huì)立刻執(zhí)行蛙奖,對(duì)于相同名稱的通知,可以添加多個(gè)觀察者杆兵。

中介者模式

中介者模式的核心是將網(wǎng)狀的對(duì)象交互結(jié)構(gòu)改為星形結(jié)構(gòu)雁仲,即所有的對(duì)象都與一個(gè)中介者進(jìn)行交互。使用中介者模式可以使原本耦合性很強(qiáng)的對(duì)象間的耦合變得松散琐脏,提高系統(tǒng)的靈活性和擴(kuò)展性攒砖。

如下代碼演示了網(wǎng)狀的對(duì)象交互結(jié)構(gòu)

class ServerA {
    func handleClientA() {
        print("ServerA 處理 ClientA 的請(qǐng)求")
    }
    func handleClientB() {
        print("ServerA 處理 ClientB 的請(qǐng)求")
    }
}
class ServerB {
    func handleClientA() {
        print("ServerB 處理 ClientA 的請(qǐng)求")
    }
    func handleClientB() {
        print("ServerB 處理 ClientB 的請(qǐng)求")
    }
}
class ClientA {
    func requestServerA() {
        ServerA().handleClientA()
    }
    func requestServerB() {
        ServerB().handleClientA()
    }
}
class ClientB {
    func requestServerA() {
        ServerA().handleClientB()
    }
    func requestServerB() {
        ServerB().handleClientB()
    }
}
let clientA = ClientA()
clientA.requestServerA()
clientA.requestServerB()
let clientB = ClientB()
clientB.requestServerA()
clientB.requestServerB()

如上所述,兩個(gè)客戶端可以分別與服務(wù)端進(jìn)行交互日裙,有時(shí)客戶端也可以點(diǎn)對(duì)點(diǎn)的與另外的客戶端進(jìn)行交互吹艇,這樣會(huì)使系統(tǒng)的結(jié)構(gòu)更加復(fù)雜,可以通過(guò)中介者模式統(tǒng)一客戶端與服務(wù)端的交互邏輯

重構(gòu)后

class ServerA {
    func handleClientA() {
        print("ServerA 處理 ClientA 的請(qǐng)求")
    }
    func handleClientB() {
        print("ServerA 處理 ClientB 的請(qǐng)求")
    }
}
class ServerB {
    func handleClientA() {
        print("ServerB 處理 ClientA 的請(qǐng)求")
    }
    func handleClientB() {
        print("ServerB 處理 ClientB 的請(qǐng)求")
    }
}
class ClientA {}
class ClientB {}
class Mediator {
    static func handler(client: AnyObject, server: AnyObject) {
        if client is ClientA {
            if server is ServerA {
                ServerA().handleClientA()
            } else {
                ServerB().handleClientA()
            }
        } else {
            if server is ServerA {
                ServerA().handleClientB()
            } else {
                ServerB().handleClientB()
            }
        }
    }
}
let clientA = ClientA()
let clientB = ClientB()
let serverA = ServerA()
let serverB = ServerB()
Mediator.handler(client: clientA, server: serverA)
Mediator.handler(client: clientA, server: serverB)
Mediator.handler(client: clientB, server: serverA)
Mediator.handler(client: clientB, server: serverB)

重構(gòu)后客戶端相關(guān)類中無(wú)須知道服務(wù)端具體的實(shí)現(xiàn)細(xì)節(jié)昂拂,中介者統(tǒng)一封裝了這些邏輯受神。

迭代器模式

軟件設(shè)計(jì)中,很多對(duì)象都是以聚合的方式組成的格侯,或者其內(nèi)部包含集合類型的數(shù)據(jù)鼻听,在訪問(wèn)對(duì)象時(shí),通常需要通過(guò)遍歷的方式獲取到其中的各個(gè)元素联四。這樣撑碴,如果對(duì)象內(nèi)部組合的方式產(chǎn)生了變化就必須對(duì)源碼進(jìn)行修改。

迭代器模式的核心是提供一個(gè)對(duì)象來(lái)訪問(wèn)聚合對(duì)象中的一系列數(shù)據(jù)朝墩,不暴露聚合對(duì)象內(nèi)部的具體實(shí)現(xiàn)醉拓,這樣即保證了類的安全性,也將內(nèi)部的集合遍歷邏輯與聚合對(duì)象本身進(jìn)行了分離收苏。

重構(gòu)后

protocol Iterator {
    associatedtype ObjectType
    var cursor: Int { get }
    func next() -> ObjectType?
    func reset()
}
class School: Iterator {
    private var teachers = [String]()
    typealias ObjectType = String
    var cursor: Int = 0
    func next() -> String? {
        if cursor < teachers.count {
            let teacher = teachers[cursor]
            cursor += 1
            return teacher
        } else {
            return nil
        }
    }
    
    func reset() {
        cursor = 0
    }
    
    func addTeacher(name: String) {
        teachers.append(name)
    }
}
let school = School()
school.addTeacher(name: "學(xué)偉")
school.addTeacher(name: "小王")
school.addTeacher(name: "喬布斯")
while let teacher = school.next() {
    print(teacher)
}
print("遍歷完成")

外界對(duì) School 內(nèi)部的數(shù)組是不感知的亿卤,使用迭代器模式可以很好的對(duì)內(nèi)部實(shí)現(xiàn)進(jìn)行封閉,外部除了通過(guò)類中暴露的函數(shù)來(lái)操作 teachers 數(shù)組外倒戏,不能直接操作怠噪。
Swift標(biāo)準(zhǔn)庫(kù)中,可以直接使用官方迭代器協(xié)議 IteratorProtocol 杜跷。

訪問(wèn)者模式

當(dāng)數(shù)據(jù)的類型固定,但對(duì)其訪問(wèn)的操作相對(duì)靈活時(shí)矫夷,可以采用訪問(wèn)者模式對(duì)軟件系統(tǒng)進(jìn)行設(shè)計(jì)葛闷。訪問(wèn)者模式的核心是將數(shù)據(jù)的處理方式從數(shù)據(jù)結(jié)構(gòu)中分離出來(lái),之后可以方便地對(duì)數(shù)據(jù)的處理方法進(jìn)行擴(kuò)展双藕。
舉一個(gè)現(xiàn)實(shí)生活中應(yīng)用訪問(wèn)者模式的例子:作為一種數(shù)據(jù)淑趾,不同的角色對(duì)其訪問(wèn)會(huì)有不同的行為表現(xiàn),對(duì)于景區(qū)門票這一數(shù)據(jù)忧陪,作為游客需要購(gòu)買扣泊,作為驗(yàn)票員需要驗(yàn)票近范,這種場(chǎng)景:

重構(gòu)后

struct Ticket {
    var name: String
}
protocol Visitor {
    func visit(ticket: Ticket)
}
class Tourist: Visitor {
    func visit(ticket: Ticket) {
        print("游客購(gòu)買\(ticket.name)")
    }
}
class Guard: Visitor {
    func visit(ticket: Ticket) {
        print("檢票員檢查了\(ticket.name)")
    }
}
let ticket = Ticket(name: "公園門票")
let tourist = Tourist()
tourist.visit(ticket: ticket)
let guarder = Guard()
guarder.visit(ticket: ticket)

如上,不同角色對(duì)門票的操作分別封裝在了獨(dú)立的類中延蟹,這使之后新增行為變得非常容易评矩,例如財(cái)務(wù)人員對(duì)門票價(jià)格進(jìn)行核對(duì)等。

備忘錄模式

備忘錄模式的定義:在不破壞封裝性的前提下阱飘,對(duì)一個(gè)對(duì)象的狀態(tài)進(jìn)行保存斥杜,在需要時(shí),可以方便地恢復(fù)到原來(lái)保存的狀態(tài)沥匈,備忘錄模式又被稱為快照模式蔗喂。
從功能上講,備忘錄模式與命令模式有許多相似之處高帖,都是提供了一種恢復(fù)狀態(tài)的機(jī)制缰儿;不同的是,命令模式是將操作封裝成命令散址,命令可以回滾乖阵,備忘錄模式則是存儲(chǔ)對(duì)象某一時(shí)刻的狀態(tài),可以將狀態(tài)進(jìn)行重置爪飘。
例如义起,很多應(yīng)用都提供了用戶自定義偏好設(shè)置的功能,偏好設(shè)置的保存與重置可以采用備忘錄模式實(shí)現(xiàn)师崎。

重構(gòu)后

protocol MementoProtocol {
    func allKeys() -> [String]
    func valueForKey(key: String) -> Any
    func setValue(value: Any, key: String)
}
class Setting: MementoProtocol {
    var setting1 = false
    var setting2 = false
    func allKeys() -> [String] {
        return ["setting1", "setting2"]
    }
    
    func valueForKey(key: String) -> Any {
        switch key {
        case "setting1":
            return setting1
        case "setting2":
            return setting2
        default:
            return ""
        }
    }
    
    func setValue(value: Any, key: String) {
        switch key {
        case "setting1":
            setting1 = value as? Bool ?? false
        case "setting2":
            setting2 = value as? Bool ?? false
        default:
            print("key: \(key) 設(shè)置錯(cuò)誤")
        }
    }
    func show() {
        print("setting1: \(setting1) ++ setting2: \(setting2)")
    }
}
class MementoManager {
    var dictionary = [String: [String: Any]]()
    func saveState(obj: MementoProtocol, stateName: String) {
        var dict = [String: Any]()
        for key in obj.allKeys() {
            dict[key] = obj.valueForKey(key: key)
        }
        dictionary[stateName] = dict
    }
    func resetState(obj: MementoProtocol, stateName: String) {
        if let dict = dictionary[stateName] {
            for kv in dict {
                obj.setValue(value: kv.value, key: kv.key)
            }
        }
    }
}
var setting = Setting()
let manager = MementoManager()
setting.setting1 = true
setting.setting2 = true
manager.saveState(obj: setting, stateName: "vip")
setting.setting2 = false
manager.saveState(obj: setting, stateName: "super")
setting.show()
manager.resetState(obj: setting, stateName: "vip")
setting.show()
manager.resetState(obj: setting, stateName: "super")
setting.show()

MementoManager 是一個(gè)快照管理類默终,可以將任何符合 MementoProtocol 協(xié)議的對(duì)象進(jìn)行快照保存。一個(gè)對(duì)象可以保存多個(gè)快照犁罩,在需要時(shí)可以方便地恢復(fù)到某個(gè)快照齐蔽。有存檔機(jī)制的軟件可以按照備忘錄設(shè)計(jì)模式的思路實(shí)現(xiàn)。

解釋器模式

定義一種簡(jiǎn)潔的語(yǔ)言床估,通過(guò)實(shí)現(xiàn)一個(gè)解釋器來(lái)對(duì)語(yǔ)言進(jìn)行解析含滴,從而實(shí)現(xiàn)邏輯。
正則表達(dá)式和iOS開(kāi)發(fā)中用于自動(dòng)布局的 VFL(Visual Format Language)是對(duì)解釋器模式的應(yīng)用丐巫。

例如谈况,在軟件中的頁(yè)面路由跳轉(zhuǎn)可以采用解釋器模式進(jìn)行設(shè)計(jì)。

重構(gòu)后

class Interpreter {
    static func handler(string: String) {
        let proto = string.components(separatedBy: "://")
        if let pro = proto.first {
            print("路由協(xié)議: \(pro)")
            if proto.count > 1, let last = proto.last {
                let path = last.split(separator: "?", maxSplits: 2, omittingEmptySubsequences: true)
                if let pathFirst = path.first {
                    print("路由路徑: \(pathFirst)")
                    if path.count > 1, let param = path.last {
                        print("路由參數(shù): \(param)")
                    }
                }
            }
        }
    }
}
Interpreter.handler(string: "http://www.xxx.com?key=value")

此類用于解析某邏輯的設(shè)計(jì)模式即解釋器模式的應(yīng)用递胧。

總結(jié)

  • 模板方法模式:定義算法骨架的前提下允許對(duì)關(guān)鍵環(huán)節(jié)的算法實(shí)現(xiàn)做修改
  • 策略模式:定義一系列方便切換的算法實(shí)現(xiàn)
  • 命令模式:將操作封裝為命令對(duì)象
  • 責(zé)任鏈模式:通過(guò)責(zé)任鏈對(duì)請(qǐng)求進(jìn)行處理碑韵,隱藏處理請(qǐng)求的對(duì)象細(xì)節(jié)
  • 狀態(tài)模式:將變化的屬性封裝為狀態(tài)對(duì)象進(jìn)行統(tǒng)一管理
  • 觀察者模式:通過(guò)監(jiān)聽(tīng)的方式處理對(duì)象間的交互邏輯
  • 中介者模式:通過(guò)定義中介者來(lái)將網(wǎng)狀結(jié)構(gòu)的邏輯改為星狀結(jié)構(gòu)
  • 迭代器模式:提供一種訪問(wèn)對(duì)象內(nèi)部集合數(shù)據(jù)的接口
  • 訪問(wèn)者模式:將數(shù)據(jù)的操作與數(shù)據(jù)本身分離
  • 備忘錄模式:通過(guò)快照的方式存儲(chǔ)對(duì)象的狀態(tài)
  • 解釋器模式:通過(guò)編寫(xiě)解釋器對(duì)自定義的簡(jiǎn)單語(yǔ)言進(jìn)行解析,從而實(shí)現(xiàn)邏輯
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缎脾,一起剝皮案震驚了整個(gè)濱河市祝闻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遗菠,老刑警劉巖联喘,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件华蜒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡豁遭,警方通過(guò)查閱死者的電腦和手機(jī)叭喜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)堤框,“玉大人域滥,你說(shuō)我怎么就攤上這事◎谧ィ” “怎么了启绰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沟使。 經(jīng)常有香客問(wèn)我委可,道長(zhǎng),這世上最難降的妖魔是什么腊嗡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任着倾,我火速辦了婚禮,結(jié)果婚禮上燕少,老公的妹妹穿的比我還像新娘卡者。我一直安慰自己,他們只是感情好客们,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布崇决。 她就那樣靜靜地躺著,像睡著了一般底挫。 火紅的嫁衣襯著肌膚如雪恒傻。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天建邓,我揣著相機(jī)與錄音盈厘,去河邊找鬼。 笑死官边,一個(gè)胖子當(dāng)著我的面吹牛沸手,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播注簿,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼罐氨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了滩援?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤塔嬉,失蹤者是張志新(化名)和其女友劉穎玩徊,沒(méi)想到半個(gè)月后租悄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恩袱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年泣棋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畔塔。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡潭辈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出澈吨,到底是詐尸還是另有隱情把敢,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布谅辣,位于F島的核電站修赞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏桑阶。R本人自食惡果不足惜柏副,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚣录。 院中可真熱鬧割择,春花似錦、人聲如沸萎河。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)公壤。三九已至换可,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厦幅,已是汗流浹背沾鳄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留确憨,地道東北人译荞。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像休弃,于是被迫代替她去往敵國(guó)和親吞歼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容