責(zé)任鏈設(shè)計(jì)模式的場(chǎng)景
問(wèn)題
? ? ? ?這里我們以一個(gè)機(jī)器師傅為例子蟹漓,每個(gè)師傅他的經(jīng)驗(yàn)技能都是不一樣的索抓,有些人比較熟練碳蛋,有些人比較生手胚泌,那么我們?cè)趺幢WC,當(dāng)訂單來(lái)了的時(shí)候肃弟,找到最合適師傅去處理這個(gè)任務(wù)呢玷室?此時(shí)零蓉,可以使用責(zé)任鏈設(shè)計(jì)模式。
解決方案
? ? ? ?我們把所有的工程師分為四種不同的等級(jí):只是加油的穷缤、初級(jí)敌蜂、學(xué)徒和熟練的工程師。每個(gè)人都有屬于自己的技能等級(jí)的標(biāo)志津肛,相同等級(jí)的人歸為一個(gè)組章喉,每一個(gè)組都有可能有更高級(jí)別的技能組存在(當(dāng)然,如果是最高技能的那個(gè)組身坐,那就沒(méi)有更高級(jí)別的組了)秸脱。這樣子分配之后,我們模擬在一個(gè)店里面部蛇,現(xiàn)在有一個(gè)任務(wù)摊唇,那么,我們應(yīng)該如何執(zhí)行呢涯鲁?按照責(zé)任鏈設(shè)計(jì)模式巷查,應(yīng)該先找最低級(jí)別的技能組,尋找是否有人能夠解決撮竿,如果不能吮便,繼續(xù)網(wǎng)下一個(gè)級(jí)別尋找,直到找到人去處理任務(wù)幢踏,或者認(rèn)為店里面已經(jīng)沒(méi)人能夠處理任務(wù)了髓需。
好,基本情況介紹到這里房蝉,下面進(jìn)行代碼拆解僚匆。。搭幻。咧擂。。
這是一條完美的分割線(xiàn)
首先我們定義一個(gè)技能表
/// 技能表
///
/// - OilChangeOnly: 只是加油的
/// - junior: 初級(jí)
/// - Apprentice: 學(xué)徒
/// - MasterMechanic: 熟練
enum Skill: Int {
case OilChangeOnly = 1, junior, Apprentice, MasterMechanic
}
接下來(lái)檀蹋,我們定義一個(gè)工作類(lèi),工作類(lèi)里面包含了需要的技能松申、工作名稱(chēng)和是否完成等屬性。
/// 工作
class Job {
let minimumSkillSet: Skill
let name: String
var completed: Bool = false
init(minimumSkillSet: Skill, name: String) {
self.minimumSkillSet = minimumSkillSet
self.name = name
}
}
有了工作俯逾,怎么能少得了干活的機(jī)器呢贸桶?同樣的,這個(gè)機(jī)器擁有技能桌肴、名稱(chēng)和是否在忙等屬性皇筛,并且他有一個(gè)去執(zhí)行工作的方法,具體坠七,請(qǐng)看代碼.....
class Mechanic {
let skill: Skill
var name: String
var isBusy: Bool = false
init(skill: Skill, name: String) {
self.skill = skill
self.name = name
}
func performJob(job: Job) -> Bool {
//該技能不在此機(jī)器的工作范圍或者該機(jī)器在忙
if job.minimumSkillSet.rawValue > self.skill.rawValue || isBusy == true {
assert(false, "This mechanic is either busy or insufficiently skilled for this job, he should have never been asked to perform it, there is something wrong in the chain of responsibility")
}else {
isBusy = true
print("\(name) with skill set \(skill) has started to do \(job.name)")
job.completed = true
return true
}
}
}
為了將擁有同樣技能的機(jī)器分類(lèi)水醋,我們?cè)俣x一個(gè)叫機(jī)器組的類(lèi)旗笔,讓他來(lái)管理所有擁有相同技能的機(jī)器。功能拄踪,看代碼你就懂了蝇恶,哈哈
class MechanicSkillGroup {
var mechanics: [Mechanic]
var nextLevel: MechanicSkillGroup?
var skill: Skill
init(skill: Skill, mechanics: [Mechanic], nextLevel: MechanicSkillGroup?) {
self.mechanics = mechanics
self.skill = skill
self.nextLevel = nextLevel
}
func performJobOrPassItUp(job: Job) -> Bool {
//當(dāng)前工作組的機(jī)器無(wú)法滿(mǎn)足功能
if job.minimumSkillSet.rawValue > skill.rawValue || mechanics.filter({$0.isBusy == false}).count == 0{
//尋找下一個(gè)機(jī)器組工作
if let nextLevel = nextLevel {
return nextLevel.performJobOrPassItUp(job: job)
}else {
print("No one is aavailable to do this job")
return false
}
}else {
//不忙又滿(mǎn)足技能要求的,隨便找一個(gè)工作就可以了
if let firstAvailavbleMechanic = mechanics.filter({$0.isBusy == false}).first {
return firstAvailavbleMechanic.performJob(job: job)
}
assert(false, "This should never be reached since our if-else statment is fully exhaustive. You cannot have both all mechanics busy and an available mechanic within one skill group")
}
}
}
最后惶桐,我們模擬一個(gè)商店類(lèi):
class Shop {
private var firstMechanics: MechanicSkillGroup
init(firstMechanics: MechanicSkillGroup) {
self.firstMechanics = firstMechanics
}
@discardableResult
func performJob(job: Job) -> Bool {
return firstMechanics.performJobOrPassItUp(job: job)
}
}
好了艘包,基本的準(zhǔn)備,我們都有了耀盗,下面我們來(lái)測(cè)試一下:
func chainOfResponsibilityTestFunction() {
/// 獲得熟練的工程師
///
/// - Returns: 熟練的工程師
func masterMechanics() -> MechanicSkillGroup {
let steve = Mechanic(skill: .MasterMechanic, name: "Steve Frank")
let joe = Mechanic(skill: .MasterMechanic, name: "Joe Alison")
let jack = Mechanic(skill: .MasterMechanic, name: "Jack Ryan")
let brian = Mechanic(skill: .MasterMechanic, name: "Drake Jin")
return MechanicSkillGroup(skill: .MasterMechanic, mechanics: [steve, joe, jack, brian], nextLevel: nil)
}
/// 獲得學(xué)徒工程師
///
/// - Returns: 學(xué)徒工程師
func apprenticeMechanics() -> MechanicSkillGroup {
let tyson = Mechanic(skill: .Apprentice, name: "Tyson Trup")
let tina = Mechanic(skill: .Apprentice, name: "Tina Bernard")
let bryan = Mechanic(skill: .Apprentice, name: "Bryan Tram")
let lin = Mechanic(skill: .Apprentice, name: "Lin Young")
return MechanicSkillGroup(skill: .Apprentice, mechanics: [tyson, tina, bryan, lin], nextLevel: masterMechanics())
}
/// 獲得初級(jí)工程師
///
/// - Returns: 初級(jí)工程師
func juniorMechanics() -> MechanicSkillGroup {
let ken = Mechanic(skill: .junior, name: "ken Hudson")
let matt = Mechanic(skill: .junior, name: "Matt Lowes")
let sandeep = Mechanic(skill: .junior, name: "Sandeep Shenoy")
let tom = Mechanic(skill: .junior, name: "Tom Berry")
return MechanicSkillGroup(skill: .junior, mechanics: [ken, matt, sandeep, tom], nextLevel: apprenticeMechanics())
}
/// 獲得只有石油改變工程師
///
/// - Returns: 只有石油改變工程師
func oilChangeOnlyesMechanics() -> MechanicSkillGroup {
let grant = Mechanic(skill: .OilChangeOnly, name: "Grant Hughes")
return MechanicSkillGroup(skill: .OilChangeOnly, mechanics: [grant], nextLevel: juniorMechanics())
}
//建造虛擬商店
let shop = Shop(firstMechanics: oilChangeOnlyesMechanics())
let jobs = [Job(minimumSkillSet: .junior, name: "Windshield Wiper"),
Job(minimumSkillSet: .Apprentice, name: "Light Bulb Change"),
Job(minimumSkillSet: .Apprentice, name: "Battery Replacement"),
Job(minimumSkillSet: .OilChangeOnly, name: "General Oil Change"),
Job(minimumSkillSet: .OilChangeOnly, name: "General Oil Change"),
Job(minimumSkillSet: .OilChangeOnly, name: "General Oil Change"),
Job(minimumSkillSet: .OilChangeOnly, name: "General Oil Change"),
Job(minimumSkillSet: .MasterMechanic, name: "Timing Belt Replacement"),
Job(minimumSkillSet: .junior, name: "Brake Pads Replacement")]
for job in jobs {
shop.performJob(job: job)
}
}
下面我們來(lái)看看打印信息:
所有的工作,都有序的進(jìn)行卦尊,但你會(huì)發(fā)現(xiàn)叛拷,一些加油這種小事情,有可能讓擁有junior技能的機(jī)器去干活岂却,這正是責(zé)任鏈設(shè)計(jì)模式特點(diǎn)忿薇,他是可以很好的分配你的工作資源,更合理的利用你的資源躏哩,在初級(jí)都在忙的情況下署浩,他會(huì)去找更高級(jí)的人去干活,而不是讓更高級(jí)的人閑著扫尺。
好了筋栋,責(zé)任鏈設(shè)計(jì)模式就介紹到這里吧,有疑問(wèn)的歡迎咨詢(xún)......
對(duì)了正驻,如果你喜歡看英文弊攘,歡迎點(diǎn)開(kāi)這個(gè)鏈接英文原文