处理对象唯一ID的IdHandler类是否需设为抽象类?实例创建位置咨询
关于你的IdHandler类的两个问题,我来分享下我的经验
首先说第一个问题:要不要把IdHandler设为抽象类?
抽象类的核心作用是定义一个「模板」,让子类去实现具体逻辑——也就是说,如果你的IdHandler本身不需要被直接实例化,而是要让不同的ID生成方式(比如UUID、自增整数、带前缀的ID)去继承它,那抽象类是合适的。但如果你的IdHandler已经有了明确的具体功能(比如生成自增的唯一ID),那完全没必要设为抽象类,直接作为一个普通的可实例化类就好。
举个例子,如果现在你的需求只是生成自增ID,那普通类就够了:
class IdHandler: def __init__(self): self._current_id = 0 def get_next_id(self): self._current_id += 1 return self._current_id
但如果以后你可能需要不同的ID生成策略(比如有的场景用UUID,有的用自增),那可以先把IdHandler做成抽象类,定义一个抽象方法get_next_id,然后让不同的子类去实现:
from abc import ABC, abstractmethod class IdHandler(ABC): @abstractmethod def get_next_id(self): pass class AutoIncrementIdHandler(IdHandler): def __init__(self): self._current_id = 0 def get_next_id(self): self._current_id += 1 return self._current_id class UUIDIdHandler(IdHandler): def get_next_id(self): import uuid return str(uuid.uuid4())
所以核心看你现在的需求和未来的扩展性——如果当前只有一种ID生成逻辑,普通类更简单;如果有多种或者未来可能扩展,抽象类是更好的选择。
然后是第二个问题:不同场景(比如不同仓库)要不要创建不同的IdHandler实例?实例放在哪里?
答案是肯定的:每个需要独立ID序列的场景,都应该有自己的IdHandler实例。比如仓库A的商品ID应该从1开始递增,仓库B的商品ID也应该从1开始,而不是跟着仓库A的序列走——这时候两个仓库就需要各自的IdHandler实例,不然ID会混在一起。
至于实例的位置,推荐两种方式:
- 在需要使用的类内部初始化:比如每个仓库类自己持有一个IdHandler实例,这样封装性更好,每个仓库的ID管理完全独立。
这样创建两个仓库的时候,它们的ID序列是完全独立的:class Warehouse: def __init__(self, name): self.name = name self.id_handler = IdHandler() # 每个仓库自己的ID处理器 self.items = {} def add_item(self, item_name): item_id = self.id_handler.get_next_id() self.items[item_id] = item_name return item_idwarehouse_a = Warehouse("A") warehouse_b = Warehouse("B") print(warehouse_a.add_item("Apple")) # 输出1 print(warehouse_b.add_item("Banana")) # 输出1 - 在应用初始化时创建全局实例,按需注入:如果你的场景比较复杂,比如多个类需要共享同一个场景的ID处理器,那可以在程序启动的时候创建好不同的IdHandler实例(比如
warehouse_a_id_handler、warehouse_b_id_handler),然后传递给需要的类。这种方式更灵活,也方便后续替换ID生成策略。
总结一下:
- 不需要一开始就把IdHandler设为抽象类,除非你明确需要多态的ID生成逻辑;
- 每个独立的ID命名空间(比如不同仓库)对应一个IdHandler实例;
- 实例最好放在需要使用它的上下文里(比如仓库类内部),或者在应用初始化时创建并注入。
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

