Python 3.10.5中基于抽象基类的方法调用分发惯用实现
符合Python风格的命令处理分发方案
先梳理你现有代码中的几个核心问题:
- 存在拼写错误:
CommandTow应为CommandTwo get_handler被定义为@property但接收参数,不符合Python属性的语法规则dispatch被定义为类方法,却调用了实例方法get_handler,逻辑矛盾- 存储的是处理类而非实例,直接调用
handle()会报错(因为handle是实例方法)
以下是修正后的实现,兼顾类型提示和Python惯用写法:
改进后的代码实现
from abc import ABC, abstractmethod from typing import Type, Dict, TypeVar # 定义类型变量,关联命令与处理类的类型关系 CommandT = TypeVar('CommandT') HandlerT = TypeVar('HandlerT', bound='BaseHandler') class BaseHandler(ABC): @abstractmethod def handle(self, command: CommandT) -> None: # 新增command参数,让处理类能直接访问命令对象的属性 pass class HandlerOne(BaseHandler): def handle(self, command: CommandT) -> None: # 可直接使用command的属性,比如command.attr1 print("执行CommandOne的处理逻辑") class HandlerTwo(BaseHandler): def handle(self, command: CommandT) -> None: print("执行CommandTwo的处理逻辑") class CommandOne: def __init__(self): self.attr1 = "命令1的专属属性" class CommandTwo: def __init__(self): self.attr2 = "命令2的专属属性" class CommandDispatcher: def __init__(self): # 直接用命令类型作为字典键,比类名字符串更可靠 self._handler_map: Dict[Type[object], Type[BaseHandler]] = { CommandOne: HandlerOne, CommandTwo: HandlerTwo, } # 若需复用处理实例,可提前初始化: # self._handler_instances = {cmd: handler() for cmd, handler in self._handler_map.items()} def get_handler(self, command: object) -> Type[BaseHandler] | None: return self._handler_map.get(type(command)) def dispatch(self, command: object) -> None: handler_cls = self.get_handler(command) if not handler_cls: raise ValueError(f"未找到命令{type(command).__name__}对应的处理类") # 实例化处理类(若复用实例则直接从_handler_instances中获取) handler = handler_cls() handler.handle(command)
客户端调用示例
dispatcher = CommandDispatcher() command_one = CommandOne() command_two = CommandTwo() dispatcher.dispatch(command_one) dispatcher.dispatch(command_two)
关键改进点说明
- 可靠的类型映射:用命令类型而非类名字符串作为字典键,彻底避免拼写错误
- 修正方法定义:将
get_handler改为普通方法,dispatch改为实例方法,符合Python语法逻辑 - 强制实现规范:把
handle设为抽象方法,确保所有处理子类必须实现该方法 - 完善类型提示:通过
typing模块的类型注解,让IDE能正确识别处理类的类型,解决你提到的类型识别问题 - 灵活的实例管理:可选择每次创建新处理实例,或提前初始化实例复用,适配不同业务场景
内容的提问来源于stack exchange,提问作者GreenyMcDuff
相关产品推荐
相关产品推荐

