我有一个Employee
实体,其中包含ContactInformation
的值对象:
Employee.php
class Employee {
private $contactInformation;
public function __construct(ContactInformation $contactInformation) {
$this->contactInformation = $contactInformation;
}
public function getContactInformation() {
return $this->contactInformation;
}
}
ContactInformation.php
class ContactInformation {
private $email; // Required
private $cellPhone; // Required
private $phone; // Optional
private $address; // Optional
public function __construct($email, $cellPhone) {
$this->email = $email;
$this->cellphone = $cellphone;
}
/** Here goes a bunch of setter getter for those properties **/
}
如果员工的电话被更改,那么
是不是更好$员工 - > getContactInformation() - > setPhone($ newPhone)
而不是强迫不可变性,如
$ employee-> setContactInformation(new ContactInformation(/ ** copy paste 这里** /));
按照Eric Evans的书,我明白当你改变一个值对象的一部分时,它就是一个完全不同的值对象,然后就是它。
我无法得到关于像ContactInformation这样的更复杂的对象的相同结论,它应该是一个实体吗?
需要建议,谢谢!
答案 0 :(得分:1)
值对象应该是不可变的,但ContactInformation
不应该是值对象。
考虑两个共享房屋的人,因此具有相同的地址和电话号码(如果您认为他们没有手机或电子邮件,则会简化问题)。
在这种情况下,他们会有相同的ContactInformation
个对象,但联系信息仍然明显是一个人或另一个人。如果他们中的一个搬出,或购买手机,那么他们的联系信息将不得不改变。
正如您在评论中提到的,最好将ContactInformation
视为可变实体,而不是值对象。
答案 1 :(得分:1)
对我而言,员工依赖ContactInformation
意味着您希望ContactInformation
已经设置了电话等,然后传递给员工,即:
$contanctInfo = new ContactInformation();
$contanctInfo->setPhone(820);
$employee1 = new Employee($contanctInfo);
echo $employee1->getContanctInformation()->getPhone(); // 820
但是,这意味着在实例化每个Employee之前,您需要生成尽可能多的ContactInformation对象,如Employee对象,因为:
$contanctInfo = new ContactInformation();
$contanctInfo->setPhone(820);
$employee1 = new Employee($contanctInfo);
$employee2 = new Employee($contanctInfo);
$employee1->getContactInformation()->setPhone(123);
$employee2->getContactInformation()->setPhone(666);
echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();
变成:
666
666
因为您正在更改同一个对象。
在您的情况下,当您在实例化ContactInformation
时使依赖变得有点无用时,您同时实例化Employee
:
$employee1 = new Employee(new ContactInformation());
$employee2 = new Employee(new ContactInformation());
$employee1->getContactInformation()->setPhone(123);
$employee2->getContactInformation()->setPhone(666);
echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();
结果:
123
666
因此,如果您不希望在将依赖对象注入其他对象之前对其进行更改,则根本不需要依赖对象。更重要的是,在现实世界中ContanctInformation
与Employee
绑定,而不是相反。
我会这样做:
class Employee {
private $_contactInformation;
public function __construct() {
$this->_contactInformation = new ContactInformation($this);
}
/**
* @return ContactInformation
*/
public function getContactInformation() {
return $this->_contactInformation;
}
}
class ContactInformation {
private $_employee;
private $email; // Required
private $cellPhone; // Required
private $phone; // Optional
private $address; // Optional
public function __construct(Employee $employee) {
$this->_employee = $employee;
}
public function setPhone($phone) {
$this->phone = $phone;
}
public function getPhone() {
return $this->phone;
}
}
$employee1 = new Employee();
$employee2 = new Employee();
$employee1->getContactInformation()->setPhone(123);
$employee2->getContanctInformation()->setPhone(666);
echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();
另一方面,如果员工有一些识别器,那么ContanctInfo
会根据ID检索信息,您可以按照自己的方式进行注射。
答案 2 :(得分:1)
有趣的讨论。我所做的是让getContactInformation返回一个克隆。
class Employee {
public function getContactInformation() {
return clone $this->contactInformation;
}
...
$contactInformation = $employee->getContactInformation();
$contactInformation->setPhone('');
$employee->setContactInformation($contactInformation);
通过这样做,实际存储在Employee中的值对象是不可变的。你总是拉一份副本,因为它不再与员工挂钩,不再是一个价值对象(人们可以争辩说有很多挥手),因此可以修改而不会扰乱DDD警察。
适合我,让我使用一个需要制定者的表格系统。