设计模式专题-责任链设计模式

2018-04-04  本文已影响44人  AndreaArlex

责任链设计模式的场景


问题
       这里我们以一个机器师傅为例子,每个师傅他的经验技能都是不一样的,有些人比较熟练,有些人比较生手,那么我们怎么保证,当订单来了的时候,找到最合适师傅去处理这个任务呢?此时,可以使用责任链设计模式

解决方案
       我们把所有的工程师分为四种不同的等级:只是加油的、初级、学徒和熟练的工程师。每个人都有属于自己的技能等级的标志,相同等级的人归为一个组,每一个组都有可能有更高级别的技能组存在(当然,如果是最高技能的那个组,那就没有更高级别的组了)。这样子分配之后,我们模拟在一个店里面,现在有一个任务,那么,我们应该如何执行呢?按照责任链设计模式,应该先找最低级别的技能组,寻找是否有人能够解决,如果不能,继续网下一个级别寻找,直到找到人去处理任务,或者认为店里面已经没人能够处理任务了。

好,基本情况介绍到这里,下面进行代码拆解。。。。。
这是一条完美的分割线


首先我们定义一个技能表

/// 技能表
///
/// - 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技能的机器去干活,这正是责任链设计模式特点,他是可以很好的分配你的工作资源,更合理的利用你的资源,在初级都在忙的情况下,他会去找更高级的人去干活,而不是让更高级的人闲着。

好了,责任链设计模式就介绍到这里吧,有疑问的欢迎咨询......
对了,如果你喜欢看英文,欢迎点开这个链接英文原文

上一篇下一篇

猜你喜欢

热点阅读