zoukankan      html  css  js  c++  java
  • [Python设计模式] 第24章 加薪审批——职责链模式

    github地址:https://github.com/cheesezh/python_design_patterns

    题目

    用程序模拟以下情景

    • 员工向经理发起加薪申请,经理无权决定,需要向总监汇报,加薪额度超过总监权力范围,需要向总经理汇报;
    • 员工还可以提交请加申请,经理可以决定2天以下的假,总监可以决定5天以下的假,其余都要上报总经理;

    基础版本

    class Request():
        
        def __init__(self):
            self.type = None  # 申请类型
            self.content = None  # 申请内容
            self.number = 0  # 申请数量
        
        
    class Manager():
        
        def __init__(self, name):
            self.name = name
            
        def get_result(self, manager_level, request):
            if manager_level == "经理":
                if request.type == "请假" and request.number <=2:
                    print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
                else:
                    print("{}:{} 数量 {} 我无权处理".format(self.name, request.content, request.number))
            elif manager_level == "总监":
                if request.type == "请假" and request.number <=5:
                    print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
                else:
                    print("{}:{} 数量 {} 我无权处理".format(self.name, request.content, request.number))
            elif manager_level == "总经理":
                if request.type == "请假":
                    print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
                elif request.type == "加薪" and request.number <= 500:
                    print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
                elif request.type == "加薪" and request.number > 500:
                    print("{}:{} 数量 {} 再说吧".format(self.name, request.content, request.number))
            
    def main():
        jingli = Manager("经理")
        zongjian = Manager("总监")
        zongjingli = Manager("总经理")
        
        request = Request()
        request.type = "加薪"
        request.content = "贺贺请求加薪"
        request.number = 1000
        
        jingli.get_result(jingli.name, request)
        zongjian.get_result(zongjian.name, request)
        zongjingli.get_result(zongjingli.name, request)
        
        request.type = "请假"
        request.content = "贺贺请求请假"
        request.number = 3
        
        jingli.get_result(jingli.name, request)
        zongjian.get_result(zongjian.name, request)
        zongjingli.get_result(zongjingli.name, request)
        
    main()
    
    经理:贺贺请求加薪 数量 1000 我无权处理
    总监:贺贺请求加薪 数量 1000 我无权处理
    总经理:贺贺请求加薪 数量 1000 再说吧
    经理:贺贺请求请假 数量 3 我无权处理
    总监:贺贺请求请假 数量 3 被批准
    总经理:贺贺请求请假 数量 3 被批准
    

    点评

    • Manager类的get_result方法比较长,有太多的分支判断,不是好的设计;
    • Mangeer类有太多的责任,违背了单一职责的原则,增加新的管理者,需要修改这个类,违背了开放封闭原则;

    职责链模式

    职责链模式,使得多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止[DP]。

    职责链模式基本结构

    from abc import ABCMeta, abstractmethod
    
    
    class Handler():
        __metaclass__ = ABCMeta
        
        def __init__(self):
            self.successor = None  # 设置继任者
            
        @abstractmethod
        def handle_request(self, request):
            pass
        
        
    class ConcretHandler1(Handler):
        """
        处理0-10的请求
        """
        def handle_request(self, request):
            if request >=0 and request < 10:
                print("handler1 handle request [ {} ]".format(request))
            elif self.successor != None:  # 由继任者处理请求
                self.successor.handle_request(request)
                
    
    class ConcretHandler2(Handler):
        """
        处理10-20的请求
        """
        def handle_request(self, request):
            if request >=10 and request < 20:
                print("handler2 handle request [ {} ]".format(request))
            elif self.successor != None:  # 由继任者处理请求
                self.successor.handle_request(request)
                
    
    class ConcretHandler3(Handler):
        """
        处理20-30的请求
        """
        def handle_request(self, request):
            if request >=20 and request < 30:
                print("handler3 handle request [ {} ]".format(request))
            elif self.successor != None:  # 由继任者处理请求
                self.successor.handle_request(request)
    
    
    def main():
        h1 = ConcretHandler1()
        h2 = ConcretHandler2()
        h3 = ConcretHandler3()
        
        h1.successor = h2
        h2.successor = h3
        
        requests = [2, 5, 14, 22, 18, 3, 27, 20]
        
        for i in requests:
            h1.handle_request(i)
            
    main()
    
    handler1 handle request [ 2 ]
    handler1 handle request [ 5 ]
    handler2 handle request [ 14 ]
    handler3 handle request [ 22 ]
    handler2 handle request [ 18 ]
    handler1 handle request [ 3 ]
    handler3 handle request [ 27 ]
    handler3 handle request [ 20 ]
    

    点评

    • 当客户提交一个请求时,请求是沿着职责链传递直至有一个ConcretHandler对象负责处理它
    • 接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构
    • 职责链可以简化对象的相互链接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接收者的引用
    • 可以随时增加或修改处理一个请求的结构,增强了给对象指派职责的灵活性
    • 一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理
    • 最重要的两点
      • 需要实现给每个具体管理者设置它的上司,也就是它的后继者
      • 需要在每个具体管理者类处理请求时,做出判断,是可以处理请求,还是必须“推卸责任”,转移到后继者

    职责链模式——加薪代码

    from abc import ABCMeta, abstractmethod
    
    
    class Manager():
        
        __metaclass__ = ABCMeta
        
        def __init__(self, name):
            self.name = name
            self.successor = None
            
        @abstractmethod
        def handle_request(self, request):
            pass
        
    
    class CommonManager(Manager):
        
        def handle_request(self, request):
            if request.type == "请假" and request.number <=2:
                print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
            elif self.successor != None:
                self.successor.handle_request(request)
                
                
    class Majordomo(Manager):
        def handle_request(self, request):
            if request.type == "请假" and request.number <=5:
                print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
            elif self.successor != None:
                self.successor.handle_request(request)
    
            
    class GeneralManager(Manager):
        def handle_request(self, request):
            if request.type == "请假":
                print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
            elif request.type == "加薪" and request.number <= 500:
                print("{}:{} 数量 {} 被批准".format(self.name, request.content, request.number))
            elif request.type == "加薪" and request.number > 500:
                print("{}:{} 数量 {} 再说吧".format(self.name, request.content, request.number))
                
                
    def main():
        jingli = CommonManager("经理")
        zongjian = Majordomo("总监")
        zongjingli = GeneralManager("总经理")
        
        jingli.successor = zongjian
        zongjian.successor = zongjingli
        
        request = Request()
        request.type = "加薪"
        request.content = "贺贺请求加薪"
        request.number = 1000
        
        jingli.handle_request(request)
        
        request.type = "请假"
        request.content = "贺贺请求请假"
        request.number = 3
        
        jingli.handle_request(request)
        
    main()
    
    总经理:贺贺请求加薪 数量 1000 再说吧
    总监:贺贺请求请假 数量 3 被批准
    

    职责链模式和状态模式

    • 职责链模式,主要处理requet和handler的问题,当handler收到requet时,判断是否自己是否可以处理,处理逻辑在handler中;
    • 状态模式,主要处理state和context的问题,当state变化时,改变context的state,继续调用context的处理逻辑,处理逻辑在context中;
  • 相关阅读:
    springcloud(3)consul
    springcloud(2)服务提供者配置及集群和信息显示改善
    springcloud(1)Eureka配置及集群
    Git操作和配合GitHub进行代码托管
    GitHub的基本使用
    关于mybatis的各种绑定(bind)错误,找不到类的情况
    springboot整合thymeleaf视图解析器
    spring boot 源码分析-------ApplicationContext
    https原理
    单例模式
  • 原文地址:https://www.cnblogs.com/CheeseZH/p/9478386.html
Copyright © 2011-2022 走看看