咨询Domain Mapper模型的通用结构是否符合行业常规
嘿,你选Stack Overflow提问这个问题完全没问题!Code Review更偏向于对已有代码做优化评审,而你问的是Data Mappers模式的通用结构这类设计模式相关的问题,在Stack Overflow会得到更多关注和专业回复的~
Data Mappers模式的通用核心结构
其实Data Mappers并没有一个绝对“刻板到不能改”的通用结构,但行业里有一套被广泛认可的核心框架,我给你拆解下:
- 实体类(Entity):这是你的纯业务模型,只专注于业务逻辑,完全不碰数据持久化的细节——比如一个
User类,只有$id、$name、$email这些属性,以及changeEmail()这类业务方法,连数据库连接字符串是什么它都不需要知道。 - 数据映射器类(Data Mapper):这就是负责“搭桥”的角色,专门处理实体和数据源(数据库、API、文件啥的)之间的转换。它通常会有这些核心方法:
findById(int $id): ?Entity:根据ID从数据源捞数据,然后把数据转换成对应的实体对象insert(Entity $entity): void:把新的实体对象的数据写入数据源update(Entity $entity): void:更新数据源里对应实体的数据delete(Entity $entity): void:从数据源删除对应实体的数据
- 数据源连接类(可选但常用):比如一个
DatabaseConnection类,专门负责和数据库建立连接、执行基础的SQL操作,映射器类会依赖这个类来完成数据读写,这样映射器不用自己处理连接细节,更符合单一职责原则。
给你举个简单的PHP例子,方便你理解:
// 实体类:纯业务模型,和数据操作完全无关 class User { private int $id; private string $name; private string $email; public function __construct(int $id, string $name, string $email) { $this->id = $id; $this->name = $name; $this->email = $email; } // 业务方法:只处理业务逻辑,比如修改邮箱时做格式校验 public function changeEmail(string $newEmail): void { if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException("无效的邮箱格式"); } $this->email = $newEmail; } // 仅提供getter,让映射器能获取实体数据用于持久化 public function getId(): int { return $this->id; } public function getName(): string { return $this->name; } public function getEmail(): string { return $this->email; } } // 数据映射器类:专门处理User实体和数据库的交互 class UserMapper { private PDO $db; public function __construct(PDO $db) { $this->db = $db; } public function findById(int $id): ?User { $stmt = $this->db->prepare("SELECT id, name, email FROM users WHERE id = ?"); $stmt->execute([$id]); $data = $stmt->fetch(PDO::FETCH_ASSOC); if (!$data) { return null; } return new User($data['id'], $data['name'], $data['email']); } public function update(User $user): void { $stmt = $this->db->prepare("UPDATE users SET name = ?, email = ? WHERE id = ?"); $stmt->execute([$user->getName(), $user->getEmail(), $user->getId()]); } }
当然,实际项目里你可能会扩展这个结构,比如加**数据传输对象(DTO)来在映射器和数据源之间传递数据,或者加仓库类(Repository)**来封装多个映射器的操作,但核心的“实体和数据操作完全分离”这个原则是不变的。
内容的提问来源于stack exchange,提问作者Matthew M
相关产品推荐
相关产品推荐

