Php DDD—访问存储库中实体的状态
我觉得我缺乏良好设计的经验,可能会使事情过于复杂,如果我这样做了,请告诉我:) 让我们看一个用户实体和用户存储库的示例。 我将从存储库开始Php DDD—访问存储库中实体的状态,php,design-patterns,domain-driven-design,Php,Design Patterns,Domain Driven Design,我觉得我缺乏良好设计的经验,可能会使事情过于复杂,如果我这样做了,请告诉我:) 让我们看一个用户实体和用户存储库的示例。 我将从存储库开始 class UserRepository { public function save(User $user) { if($user->getStatus() == User::STATUS_NEW) $this->getDataAccessObject()->insert($user->getState())
class UserRepository {
public function save(User $user) {
if($user->getStatus() == User::STATUS_NEW)
$this->getDataAccessObject()->insert($user->getState());
else
$this->getDataAccessObject()->update($user->getState());
$user->setStatus(User::STATUS_MANAGED);
}
}
以及用户自己
class UserEntity {
const STATUS_NEW = 1;
const STATUS_MANAGED = 2;
private $_status = self::STATUS_NEW;
private $_state = array();
public static function create($username, $password) {
return new UserEntity(array('Username' => $username, 'Password' => $password));
}
public function __construct(array $state) {
$this->_state = $state;
}
public function getState() {
return $this->_state;
}
public function getStatus() {
return $this->_status;
}
public function setStatus($status) {
$this->_status = $status;
}
}
在我提问之前,关于代码的注释很少:
class Entity {
public static function create($identity, $param1, $param2, Repository $r) {
$state = $r->getNewState($identity, $param1, $param2);
return new Entity($state);
}
private $_state = null;
public function __construct(State $state) {
$this->_state = $state;
}
public function getIdentity() {
$this->_state->getIdentity();
}
}
class Repository {
private $_states = array();
public function getNewState($identity, ...) {
$state = new State($identity, ...);
$this->_states[$identity] = $state;
return $state;
}
public function save(Entity $entity) {
$id = $entity->getIdentity();
//maybe check if such entity is managed by this repository..
if($this->_states[$id]->getStatus() === State::STATUS_NEW)
$this->getDataAccessObject()->insert($this->_states[$id]->toArray());
else
$this->getDataAccessObject()->update($this->_states[$id]->toArray());
$this->_states[$id]->setStatus(State::STATUS_MANAGED);
}
}
class State {
const STATUS_NEW = 1;
const STATUS_MANAGED = 2;
private $_state = array()
private $_identity = 'something';
public function getIdentity() {
return $this->_state[$this->_identity];
}
public function toArray() {
return $this->_state;
}
}
我觉得它“更正确”,因为在这里我不公开实体的内部状态,只有存储库知道它
那你觉得呢?实体的内部状态是否正常?或者第二个例子是设计这种系统的更好方法?或者你知道更好的方法
多谢各位
这些方法只能在存储库中使用
class UserRepository {
public function save(User $user) {
if($user->getStatus() == User::STATUS_NEW)
$this->getDataAccessObject()->insert($user->getState());
else
$this->getDataAccessObject()->update($user->getState());
$user->setStatus(User::STATUS_MANAGED);
}
}
如果需要,请使每个实体和存储库本身具有相同的基类,而实体getter/setter是其受保护的成员。这样做是受保护的,不再公开
这将使存储库和实体更加紧密地结合在一起,这在您的情况下可能并不坏,因为存储库产生了实体
这些方法只能在存储库中使用
class UserRepository {
public function save(User $user) {
if($user->getStatus() == User::STATUS_NEW)
$this->getDataAccessObject()->insert($user->getState());
else
$this->getDataAccessObject()->update($user->getState());
$user->setStatus(User::STATUS_MANAGED);
}
}
如果需要,请使每个实体和存储库本身具有相同的基类,而实体getter/setter是其受保护的成员。这样做是受保护的,不再公开
这将使存储库和实体更紧密地结合在一起,这在您的情况下可能并不坏,因为存储库产生了实体。首先:不要对实体和存储库使用单一基类;它们没有关系,你这样做会打破每一条坚实的原则:) 有很多不同的方法可以做到这一点。首先想到的是DAO,即数据访问对象模式。我注意到您在存储库实现中使用了这个术语,但我认为您的使用有点倒退。。。通常一个实体会有一个对应的DAO,它负责持久化那个特定的实体
UserEntity myEntity = new UserEntity("username","password");
UserDAO myDAO = new UserDAO(myEntity)
myDao.Create();
或
在这种情况下,UserDAO和UserEntity都可以扩展DTO基类,您可以在实体中保留业务逻辑,在DAO中保留持久性代码,从而消除字段和(shiver)属性的所有重复。实体将承担业务逻辑的单一责任,DAO将承担持久性的单一责任。存储库模式可用于抽象存储基础结构,但在使用DAOs时,它通常不值得
public class UserDTO
{
protected bool banned;
protected string username;
protected string password;
}
public class UserEntity : UserDTO
{
public void BlockUser();
public void ChangePassword();
}
public class UserDAO : UserDTO
{
private int Id;
public void Create();
public void Update();
public UserEntity GetByUsername(string userName);
public void Delete();
}
现在这看起来可能和hakre说的一样,但是在Repository模式和DAO模式之间有很大的区别
如果我对PHP中的成员可见性选项有所了解(比如,除了public/private/protected?internal之外,您还有其他作用域吗?)
编辑:我刚想到我在方法签名中给出了一些误导性的信息;一个DAO不应该返回一个实体,一个实体应该有一个构造函数获取一个DAO,并从中创建一个新的DAO
编辑2:另一种方法是将UserEntity视为值对象。不要为国家公开一个setter,而是公开一个getter。存储库使用它获取数据,并在检索实体时通过构造函数简单地传递所有属性。但是,这会对如何使用用户对象产生一些影响,这也是我之前没有建议的原因。首先:不要对实体和存储库使用单个基类;它们没有关系,你这样做会打破每一条坚实的原则:) 有很多不同的方法可以做到这一点。首先想到的是DAO,即数据访问对象模式。我注意到您在存储库实现中使用了这个术语,但我认为您的使用有点倒退。。。通常一个实体会有一个对应的DAO,它负责持久化那个特定的实体
UserEntity myEntity = new UserEntity("username","password");
UserDAO myDAO = new UserDAO(myEntity)
myDao.Create();
或
在这种情况下,UserDAO和UserEntity都可以扩展DTO基类,您可以在实体中保留业务逻辑,在DAO中保留持久性代码,从而消除字段和(shiver)属性的所有重复。实体将承担业务逻辑的单一责任,DAO将承担持久性的单一责任。存储库模式可用于抽象存储基础结构,但在使用DAOs时,通常是这样