uyl*_*lmz 2 java oop domain-driven-design
一个人有身份证.学生有学生证.司机有驾驶执照.
这些事情是否只是状态改变,如下例所示:
class Person {
ID id;
StudentID stId;
DriverLicense license;
void drive() {
if(license == null) //illegal state exception
//drive
}
//bla bla
}
Run Code Online (Sandbox Code Playgroud)
还是继承?由于对象是数据+行为,新数据和能够做新事物应该保证新对象
class Student extends Person {
//
}
class Driver extends Person {
//
}
//things get messy here, in Java you can't extend multiple class
//what if there's a rule that, student drivers can request/get a tax reduction?
class DriverStudent extends Person, Driver {
//
}
Run Code Online (Sandbox Code Playgroud)
加上,更重要的是,一个人如何成为另一个?通过方法或构造函数或第三类(如服务或聚合)?
class Person {
Driver getADriversLicense() {
//create and return a Driver
//this person still exists but now there's a driver with this person's data
}
}
or:
class Driver extends Person {
public Driver(Person p) {
//constructor
}
}
or:
class Aggregate {
Driver giveDriversLicense(Person p) {
// access internal state of both objects(ditch encapsulation) and return a driver?
// put aggregate in same package with Driver and Person and use package private methods to provide encapsulation?
}
}
Run Code Online (Sandbox Code Playgroud)
看到这种关系的更好方法是通过角色,即一个人可以扮演多个角色.
一个人可以成为一名驾驶员和一名学生,也可能是一名员工的场景怎么样?
所以IMO最好代表如下 -
class Person{
List<Role> currentRoles ;
List<Role> getCurrentRoles(){
return currentRoles ;
}
public void addRole(Role role){
currentRoles.add(role) ; // so on
}
}
Run Code Online (Sandbox Code Playgroud)
使用泛型和类型安全转换,您可以轻松检索特定角色并在其上调用相关操作.
public interface DriverRole implements Role {
License getDriversLicense() ;
}
Run Code Online (Sandbox Code Playgroud)
编辑:进一步完全回答您的问题,它可以轻松解决人员获得或失去角色的情况,即添加或删除角色.正如评论中所指出的,这种关系最好通过Has <0..M>关系表示,然后是IS - 关系.
编辑1相比之下,当您使用Decorator模式时,您的原点被包装,太多的装饰器可以创建一个聚合链,IMO不是理想的场景,或者它会导致装饰器继承链不符合我的喜好.
已经说过,根据具体的情况,一个特定的模式可能比另一个更合适,但在你给出的例子中我认为角色的简单聚合是最好的.