DEV Community

架构师小白
架构师小白

Posted on

仓储模式深度指南:构建数据访问抽象的艺术

仓储模式深度指南:构建数据访问抽象的艺术

在软件开发中,数据访问往往是业务逻辑与持久化层之间的桥梁。直接操作数据库代码散落在业务各处,会导致难以维护的紧耦合。仓储模式(Repository Pattern)正是为解决这一问题而生的经典架构模式。


什么是仓储模式?

仓储模式是一种抽象数据访问层的模式。它在业务逻辑层与数据源之间引入了一个中间层,统一管理数据的增删改查操作,使业务层完全不关心数据来自哪里——可能是MySQL、MongoDB、Redis,甚至是外部API。

核心概念

1. 接口契约

仓储模式的核心是定义统一的接口:

from abc import ABC, abstractmethod
from typing import TypeVar, Generic, List, Optional

T = TypeVar("T")

class Repository(ABC, Generic[T]):
    @abstractmethod
    def find_by_id(self, id: str) -> Optional[T]:
        pass

    def find_all(self) -> List[T]:
        pass

    def save(self, entity: T) -> T:
        pass

    def delete(self, id: str) -> bool:
        pass
Enter fullscreen mode Exit fullscreen mode

2. 实现解耦

同一接口可以有多个实现:

class UserRepositoryMySQL(UserRepository):
    def __init__(self, connection):
        self.db = connection

    def find_by_id(self, id: str) -> Optional[User]:
        cursor = self.db.cursor()
        cursor.execute("SELECT * FROM users WHERE id = ?", (id,))
        row = cursor.fetchone()
        return User.from_row(row) if row else None
Enter fullscreen mode Exit fullscreen mode

为什么需要仓储模式?

单一职责

业务逻辑只需关心"如何用数据",不关心"数据从哪来"。

可测试性

通过Mock仓储实现,可以在不连接数据库的情况下测试业务逻辑。

class MockUserRepository(UserRepository):
    def __init__(self):
        self.store = {}

    def find_by_id(self, id: str) -> Optional[User]:
        return self.store.get(id)
Enter fullscreen mode Exit fullscreen mode

灵活切换数据源

需要从MySQL迁移到PostgreSQL?只需要新增一个实现类,业务代码无需改动。

仓储模式 vs DAO

特征 仓储模式 DAO
抽象层级 领域模型 数据表
关注点 业务对象 数据操作
粒度 粗粒度 细粒度

仓储模式更面向业务,DAO更面向数据库。实际项目中,两者常配合使用。

实践建议

  1. 一个聚合根一个仓储——如Order和OrderItem属于同一个仓储
  2. 避免事务泄漏——事务应在应用服务层管理
  3. 适度抽象——小型项目可直接省略,过度工程反而增加复杂度

总结

仓储模式是实现数据访问层抽象的利器,它让业务代码与数据源解耦,提升了系统的可维护性和可测试性。在微服务架构、DDD实践中,仓储模式仍是数据层的首选抽象方式。

Top comments (0)