美文网首页
设计模式专题-责任链设计模式

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

作者: AndreaArlex | 来源:发表于2018-04-04 10:08 被阅读44次

    责任链设计模式的场景


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

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

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


    首先我们定义一个技能表

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

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

    相关文章

      网友评论

          本文标题:设计模式专题-责任链设计模式

          本文链接:https://www.haomeiwen.com/subject/zzychftx.html