python 中的 DAO 模式

less than 1 minute read

在学习 Redis University 的 RU102PY-Week1 课程时,遇到了 DAO 模式。之前一直以为这种都是 Java 领域的概念,看来是误解了。

wiki 中的定义是:

数据访问对象(data access object,DAO)是为某种类型的数据库或其他持久性机制提供一个抽象接口的对象。通过映射应用程序对持久层的调用,DAO提供一些特定的数据操作,而无需暴露数据库细节。

回过头来看课程中使用 DAO 的场景。和数据库打交道时需要定义三个类:

  • 代表业务领域模型(model)的类,通常只有属性, gettersetter。类似于 Java 中的 POJO
  • 定义了和存储层交互的抽象方法或接口的抽象基类,也就是 DAOBase。这些接口是和具体存储方式无关的。
  • 对应于某种具体存储方式,实现了上述接口的具体类,例如 DAORedisDAOPgsql

You can think of DAO as a design pattern that separates the interface for querying data from implementations of that interface that are specific to data stores like Redis or Postgres.

两个字,解耦。

借用课程中的图来展示得更清楚一些: DAO Pattern Diagram

注意到:

  • Model 层使用了 Python3 的新特性 dataclass 来定义模型,使得代码更简洁。
@dataclass(frozen=True, eq=True)
class Site:
    """A solar power installation."""
    id: int
    capacity: float
    panels: int
    address: str
    city: str
    state: str
    postal_code: str
    coordinate: Union[Coordinate, None] = None
  • DAO 抽象类继承了 abstract base class (ABC),并定义了一系列 abc.abstractmethod
class SiteDaoBase(abc.ABC):
    @abc.abstractmethod
    def insert(self, site: Site) -> None:
        pass

    @abc.abstractmethod
    def insert_many(self, *sites: Site) -> None:
        pass

    @abc.abstractmethod
    def find_by_id(self, site_id: int) -> Site:
        pass

    @abc.abstractmethod
    def find_all(self) -> Set[Site]:
        pass 

关于 dataclass 和 ABC,值得另开笔记来学习。

Comments