【发布时间】:2012-02-11 14:38:23
【问题描述】:
我觉得我缺乏好的设计经验,我可能会把事情复杂化,如果我这样做了,请告诉我:)
让我们看一个用户实体和用户存储库的示例。 我将从存储库开始
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;
}
}
在我问这个问题之前,关于代码的注释很少:
它的php(难懂的C++\C#\Java应该很容易理解)
为了示例的简单性,我省略了基类(如抽象存储库和抽象实体,UserRepository 和 UserEntity 从中继承)。
我放弃了工厂对象/类模式,而是更喜欢在自身的实体中使用工厂方法模式。
-
工厂方法在这个例子中看起来是多余的,可以替换为
$user = UserEntity(array('Username' => $username, 'Password' => $password));
但实际上它有点复杂,因为工厂接受“原始”数据(例如来自 POST 表单)并创建所有需要的实体或值对象,然后创建一个有效的用户实体(所以实体中的密码可能不是真正的密码,而是一个包含密码哈希而不是密码的值对象。
现在问题来了:
我并不完整,因为我向世界公开了 getState() 和 setStatus() 方法。这些方法应该只在存储库中使用,但由于它们是公共的,没有什么能阻止我在任何地方访问实体的状态和/或修改它的状态。同样,这可能是过度反应和过度复杂化,但我觉得它不对。
我找到的唯一“解决方案”是通过存储库传递所有内容,例如
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;
}
}
对我来说它看起来“更正确”,因为在这里我不公开实体的内部状态,只有存储库知道它。
那你怎么看?暴露实体的内部状态可以吗?或者也许第二个例子是设计这种系统的更好方法?或者你知道更好的方法?
非常感谢!
【问题讨论】:
标签: php design-patterns domain-driven-design