责任链设计模式的场景
问题
这里我们以一个机器师傅为例子,每个师傅他的经验技能都是不一样的,有些人比较熟练,有些人比较生手,那么我们怎么保证,当订单来了的时候,找到最合适师傅去处理这个任务呢?此时,可以使用责任链设计模式。
解决方案
我们把所有的工程师分为四种不同的等级:只是加油的、初级、学徒和熟练的工程师。每个人都有属于自己的技能等级的标志,相同等级的人归为一个组,每一个组都有可能有更高级别的技能组存在(当然,如果是最高技能的那个组,那就没有更高级别的组了)。这样子分配之后,我们模拟在一个店里面,现在有一个任务,那么,我们应该如何执行呢?按照责任链设计模式,应该先找最低级别的技能组,寻找是否有人能够解决,如果不能,继续网下一个级别寻找,直到找到人去处理任务,或者认为店里面已经没人能够处理任务了。
好,基本情况介绍到这里,下面进行代码拆解。。。。。
这是一条完美的分割线
首先我们定义一个技能表
/// 技能表
///
/// - OilChangeOnly: 只是加油的
/// - junior: 初级
/// - Apprentice: 学徒
/// - MasterMechanic: 熟练
enum Skill: Int {
case OilChangeOnly = 1, junior, Apprentice, MasterMechanic
}
接下来,我们定义一个工作类,工作类里面包含了需要的技能、工作名称和是否完成等属性。
/// 工作
class Job {
let minimumSkillSet: Skill
let name: String
var completed: Bool = false
init(minimumSkillSet: Skill, name: String) {
self.minimumSkillSet = minimumSkillSet
self.name = name
}
}
有了工作,怎么能少得了干活的机器呢?同样的,这个机器拥有技能、名称和是否在忙等属性,并且他有一个去执行工作的方法,具体,请看代码.....
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 {
//该技能不在此机器的工作范围或者该机器在忙
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
}
}
}
为了将拥有同样技能的机器分类,我们再定义一个叫机器组的类,让他来管理所有拥有相同技能的机器。功能,看代码你就懂了,哈哈
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 {
//当前工作组的机器无法满足功能
if job.minimumSkillSet.rawValue > skill.rawValue || mechanics.filter({$0.isBusy == false}).count == 0{
//寻找下一个机器组工作
if let nextLevel = nextLevel {
return nextLevel.performJobOrPassItUp(job: job)
}else {
print("No one is aavailable to do this job")
return false
}
}else {
//不忙又满足技能要求的,随便找一个工作就可以了
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")
}
}
}
最后,我们模拟一个商店类:
class Shop {
private var firstMechanics: MechanicSkillGroup
init(firstMechanics: MechanicSkillGroup) {
self.firstMechanics = firstMechanics
}
@discardableResult
func performJob(job: Job) -> Bool {
return firstMechanics.performJobOrPassItUp(job: job)
}
}
好了,基本的准备,我们都有了,下面我们来测试一下:
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)
}
/// 获得学徒工程师
///
/// - Returns: 学徒工程师
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())
}
/// 获得初级工程师
///
/// - Returns: 初级工程师
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)
}
}
下面我们来看看打印信息:
image.png
所有的工作,都有序的进行,但你会发现,一些加油这种小事情,有可能让拥有junior技能的机器去干活,这正是责任链设计模式特点,他是可以很好的分配你的工作资源,更合理的利用你的资源,在初级都在忙的情况下,他会去找更高级的人去干活,而不是让更高级的人闲着。
好了,责任链设计模式就介绍到这里吧,有疑问的欢迎咨询......
对了,如果你喜欢看英文,欢迎点开这个链接英文原文
网友评论