我目前的情况是我有一个abstract
模型,许多其他模型继承自该模型。 API使用“DTO”对象,该对象本质上是一个包含每个子类的所有可能字段的大对象,这是由于客户端调用服务。我为此创建了一个解决方案,但感觉它有一些不好的“气味”。以下是设置示例:
public abstract class Person {
public Long id;
public Long name;
}
public class Employee extends Person {
public Date startDate;
}
public class Student extends Person {
public Double gpa;
}
public class PersonDTO {
public Long id;
public String name;
public Date startDate;
public Double gpa;
public String type;
}
我想通过初始化将DTO转换为具体的子类。我已经通过创建工厂并覆盖每个子类中的方法来解决这个问题:
public class PersonFactory {
public Person getInstance(String type) {
if (type.equals("Student")) {
return new Student();
} else if (type.equals("Employee")) {
return new Employee();
}
return null;
}
}
public class Student extends Person {
public Double gpa;
/**
* Initializes the additional fields in the subclass
* from the PersonDTO.
*/
@Override
public void initialize(PersonDTO dto) {
this.gpa = dto.gpa;
}
}
所以调用类将执行以下操作:
public Person createPerson(PersonDTO dto) {
Person person = new PersonFactory().getInstance(dto.type);
person.name = dto.name;
person.id = dto.id;
person.initialize(dto);
}
为了更多地考虑这个问题,模型超类(在这个例子中,Person
)有大约15个字段,子类最多可以有5或6个,这使得使用构造函数很麻烦。我觉得让initialize
方法是一种不好的做法,并将Person类与DTO类相结合(这也违反了Law of Demeter)。
理想情况下,我想创建一个Mapper
或Translator
类,将DTO转换为具体的子类,但我在初始化公共字段时遇到了以下问题: / p>
public class PersonMapper implements Mapper<PersonDTO, Person> {
public Person map(PersonDTO dto) {
if (dto.type.equals("Student")) {
Student person = new Student();
setupCommonFields(person, dto); // required to call this method
person.gpa = dto.gpa; // inside of every block
return person;
} else if (dto.type.equals("Employee")) {
Employee person = new Employee();
setupCommonFields(person, dto);
person.startDate = dto.startDate;
return person;
}
}
private void setupCommonFields(Person person, PersonDTO dto) {
person.id = dto.id;
person.name = dto.name;
}
}
这似乎是一个非常简单的问题需要解决,但我似乎无法想出最完美的解决方案。是否有更好的解决方案?
答案 0 :(得分:2)
public class PersonMapper implements Mapper<PersonDTO, Person> {
public Person map(PersonDTO dto) {
Person person = createPerson(dto);
setupCommonFields(person, dto);
return person;
}
private Person createPerson(PersonDTO dto) {
if (person.type.equals("Student")) {
Student person = new Student();
person.gpa = dto.gpa;
return person;
} else if (person.type.equals("Employee")) {
Employee person = new Employee();
person.startDate = dto.startDate;
return person;
}
}
private void setupCommonFields(Person person, PersonDTO dto) {
person.id = dto.id;
person.name = dto.name;
}
}