下面通过一个校园后勤管理系统的优化案例,展示 Python 面向对象设计的核心思想与实践技巧。该系统主要管理校园资产(设备、家具等)、维修记录、仓库库存等核心业务,优化重点在于职责拆分扩展性提升数据一致性保障

一、系统痛点分析(优化前)

  1. 单一大类封装所有功能(违反单一职责原则),如LogisticsSystem类同时处理资产管理、维修记录、库存统计
  2. 资产类型硬编码(如if-else判断设备 / 家具),新增类型需修改核心代码
  3. 缺乏数据验证与状态管理,资产状态(在用 / 维修 / 报废)变更混乱
  4. 未实现数据持久化,程序重启后数据丢失

二、优化方案设计(面向对象核心思想)

1. 类结构设计(基于职责拆分)

plaintext

├── 核心实体类(数据与基础行为)
│   ├── Asset(资产抽象基类)
│   │   ├── Device(设备资产,如投影仪)
│   │   └── Furniture(家具资产,如课桌)
│   ├── Person(人员抽象基类)
│   │   ├── Staff(后勤人员)
│   │   └── Student(学生,用于报修)
│   ├── MaintenanceRecord(维修记录)
│   └── Warehouse(仓库,管理库存)

├── 服务类(业务逻辑)
│   ├── AssetManager(资产管理:新增/报废/状态变更)
│   ├── MaintenanceManager(维修管理:报修/派工/结案)
│   └── DataPersistence(数据持久化:序列化/反序列化)

└── 工具类(辅助功能)
    ├── AssetFactory(资产工厂:创建不同类型资产)
    └── Validator(数据验证:确保资产信息完整)

2. 核心代码实现(优化后)
(1)实体类设计(封装数据与基础行为)

python

运行

from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional, Dict


# 抽象基类:资产
class Asset(ABC):
    def __init__(self, asset_id: str, name: str, location: str):
        self.asset_id = asset_id  # 资产唯一标识
        self.name = name          # 资产名称
        self.location = location  # 存放位置
        self._status = "in_use"   # 状态:in_use/repairing/scrapped
        self.created_at = datetime.now()
        
    @property
    def status(self) -> str:
        return self._status
    
    @status.setter
    def status(self, new_status: str) -> None:
        """状态变更验证"""
        valid_status = {"in_use", "repairing", "scrapped"}
        if new_status not in valid_status:
            raise ValueError(f"无效状态:{new_status},必须是{valid_status}")
        self._status = new_status
    
    @abstractmethod
    def get_type(self) -> str:
        """获取资产类型(多态)"""
        pass


# 设备资产(继承自Asset)
class Device(Asset):
    def __init__(self, asset_id: str, name: str, location: str, brand: str):
        super().__init__(asset_id, name, location)
        self.brand = brand  # 设备品牌(特有属性)
    
    def get_type(self) -> str:
        return "device"


# 家具资产(继承自Asset)
class Furniture(Asset):
    def __init__(self, asset_id: str, name: str, location: str, material: str):
        super().__init__(asset_id, name, location)
        self.material = material  # 材质(特有属性)
    
    def get_type(self) -> str:
        return "furniture"


# 维修记录(关联资产与人员)
@dataclass
class MaintenanceRecord:
    record_id: str
    asset: Asset  # 关联资产对象
    reporter: "Person"  # 报修人
    handler: Optional["Staff"] = None  # 处理人(可选)
    description: str = ""  # 故障描述
    status: str = "pending"  # pending/processing/completed
    created_at: datetime = datetime.now()
    completed_at: Optional[datetime] = None
(2)服务类设计(业务逻辑与职责分离)

python

运行

# 资产工厂(工厂模式:创建不同类型资产,避免硬编码)
class AssetFactory:
    @staticmethod
    def create_asset(asset_type: str, **kwargs) -> Asset:
        if asset_type == "device":
            return Device(** kwargs)
        elif asset_type == "furniture":
            return Furniture(**kwargs)
        else:
            raise ValueError(f"不支持的资产类型:{asset_type}")


# 资产管理类(单一职责:只处理资产生命周期)
class AssetManager:
    def __init__(self):
        self.assets: Dict[str, Asset] = {}  # asset_id -> Asset
    
    def add_asset(self, asset: Asset) -> None:
        if asset.asset_id in self.assets:
            raise ValueError(f"资产ID已存在:{asset.asset_id}")
        self.assets[asset.asset_id] = asset
    
    def scrap_asset(self, asset_id: str) -> None:
        """报废资产(状态变更+业务逻辑)"""
        asset = self.assets.get(asset_id)
        if not asset:
            raise ValueError(f"资产不存在:{asset_id}")
        if asset.status == "repairing":
            raise RuntimeError(f"资产{asset_id}正在维修,无法报废")
        asset.status = "scrapped"
    
    def get_assets_by_status(self, status: str) -> List[Asset]:
        return [a for a in self.assets.values() if a.status == status]


# 维修管理类(单一职责:处理维修流程)
class MaintenanceManager:
    def __init__(self, asset_manager: AssetManager):
        self.records: Dict[str, MaintenanceRecord] = {}
        self.asset_manager = asset_manager  # 依赖注入:复用资产管理
    
    def create_repair_request(self, record: MaintenanceRecord) -> None:
        """创建报修单(自动更新资产状态)"""
        asset = record.asset
        if asset.status == "scrapped":
            raise RuntimeError(f"报废资产{asset.asset_id}无法报修")
        
        self.records[record.record_id] = record
        asset.status = "repairing"  # 报修后自动改为维修中
    
    def complete_repair(self, record_id: str, handler: "Staff") -> None:
        """完成维修(更新记录+资产状态)"""
        record = self.records.get(record_id)
        if not record:
            raise ValueError(f"维修记录不存在:{record_id}")
        
        record.status = "completed"
        record.handler = handler
        record.completed_at = datetime.now()
        record.asset.status = "in_use"  # 维修完成后改回在用
(3)数据持久化(基于动态属性序列化)

复用之前的动态属性序列化方案,支持资产动态属性(如临时添加的warranty_period保修期限):

python

运行

import json
from typing import Any


class DataPersistence:
    @staticmethod
    def serialize(obj: Any) -> str:
        """序列化对象(支持Asset、MaintenanceRecord等)"""
        def _convert(obj):
            if isinstance(obj, datetime):
                return obj.isoformat()
            if isinstance(obj, Asset):
                data = {
                    "type": obj.get_type(),
                    "attrs": obj.__dict__,
                    "class": obj.__class__.__name__
                }
                return data
            if isinstance(obj, MaintenanceRecord):
                return {
                    "record_id": obj.record_id,
                    "asset_id": obj.asset.asset_id,  # 存储关联ID而非对象
                    "reporter_id": obj.reporter.person_id,
                    "handler_id": obj.handler.person_id if obj.handler else None,
                    "description": obj.description,
                    "status": obj.status,
                    "created_at": _convert(obj.created_at),
                    "completed_at": _convert(obj.completed_at) if obj.completed_at else None
                }
            return obj.__dict__ if hasattr(obj, '__dict__') else obj
        
        return json.dumps(obj, default=_convert, indent=2)
    
    @staticmethod
    def deserialize(json_str: str, asset_manager: AssetManager) -> Any:
        """反序列化(需关联资产管理器恢复对象引用)"""
        data = json.loads(json_str)
        # 简化实现:根据实际需求恢复对象
        return data
(4)系统集成与使用示例

python

运行

# 人员类(简化实现)
class Person(ABC):
    def __init__(self, person_id: str, name: str):
        self.person_id = person_id
        self.name = name

class Staff(Person):
    pass

class Student(Person):
    pass


# 系统初始化
if __name__ == "__main__":
    # 1. 创建核心组件
    asset_manager = AssetManager()
    maintenance_manager = MaintenanceManager(asset_manager)
    factory = AssetFactory()
    
    # 2. 添加资产(通过工厂模式)
    projector = factory.create_asset(
        "device",
        asset_id="D001",
        name="投影仪",
        location="教学楼301",
        brand="明基"
    )
    # 动态添加属性(如保修期限)
    projector.warranty_period = "2年"
    asset_manager.add_asset(projector)
    
    desk = factory.create_asset(
        "furniture",
        asset_id="F001",
        name="课桌",
        location="教学楼301",
        material="实木"
    )
    asset_manager.add_asset(desk)
    
    # 3. 创建人员
    student = Student("S1001", "张三")
    staff = Staff("ST001", "李四(维修工)")
    
    # 4. 提交报修
    repair_record = MaintenanceRecord(
        record_id="R001",
        asset=projector,
        reporter=student,
        description="无法开机"
    )
    maintenance_manager.create_repair_request(repair_record)
    print(f"报修后投影仪状态:{projector.status}")  # 输出:repairing
    
    # 5. 完成维修
    maintenance_manager.complete_repair("R001", staff)
    print(f"维修后投影仪状态:{projector.status}")  # 输出:in_use
    
    # 6. 数据持久化
    serialized_data = DataPersistence.serialize({
        "assets": asset_manager.assets,
        "repairs": maintenance_manager.records
    })
    with open("logistics_data.json", "w") as f:
        f.write(serialized_data)

三、优化亮点总结

  1. 单一职责原则:每个类只负责一项功能(如AssetManager仅管理资产,MaintenanceManager仅处理维修),降低耦合度。

  2. 多态与工厂模式:通过Asset抽象基类定义接口,Device/Furniture实现多态;AssetFactory统一创建资产,新增资产类型(如ElectricalAppliance电器)时无需修改核心逻辑。

  3. 状态管理与数据验证:资产状态通过@property封装,确保变更合法性;维修流程中自动同步资产状态(如报修后自动改为 "维修中")。

  4. 动态属性与序列化:支持资产动态添加属性(如保修期限),通过自定义序列化方案实现完整数据持久化。

  5. 依赖注入MaintenanceManager通过参数接收AssetManager,而非内部创建,提高代码可测试性与灵活性。

四、进一步优化方向

  1. 引入观察者模式:当资产状态变更时,自动通知仓库管理员或相关师生。
  2. 添加缓存层:对高频访问的资产信息(如教学设备位置)进行缓存,提升查询性能。
  3. 实现数据库持久化:替换 JSON 文件存储,使用 SQLAlchemy 等 ORM 工具对接 MySQL,支持事务与并发控制。
  4. 增加权限控制:通过装饰器或代理模式限制不同角色(学生 / 管理员)的操作权限。

通过面向对象设计的优化,系统从 "一锅粥" 的代码结构转变为职责清晰、可扩展、易维护的模块化架构,为后续功能迭代奠定了良好基础。

更多推荐