该站点的 css/js 不起作用,因此答案可能未格式化。
我更喜欢第二种解决方案。但是我使用了一个变体,例如
public class PersonDetailViewAdapter {
private Person person
private PersonStatusDict personStatusDict;
public PersonDetailViewAdapter(Person person, PersonStatusDict personStatusDict) {
this.person = person;
this.personStatusDict = personStatusDict;
}
public String getAge() {//you don't have to use a field
return person.getAge()//age calculation seems to be a domain logic
}
public String getStatusName() {
return personStatusDict.translate(person.getStatus());
}
}
但这实际上取决于您的观点的复杂性。如果视图要求是直截了当的,那么编写这样一个包装器是很无聊的,那么你最终会得到一个包装器,每个方法都只是委托给被包装的实体(假设,状态字典非常简单,不需要外部依赖,例如从数据源查找,则 Person.getStatusName() 更方便)。在这种情况下,我会选择第一个解决方案。
下面是我的视图适配器的示例:
public class AirTicketDetailViewAdapter {
private AirTicket ticket;
public AirTicketDetailViewAdapter(AirTicket ticket) {
this.ticket = ticket;
}
public String getId() {
return ticket.getId();//avoid train wreck code
}
public String getNumber() {
//avoid dispaly null, this attribute is empty if not ticketed
return ObjectUtils.nullSafeTrim(ticket.getNumber());
}
public String getRemark() {
return ObjectUtils.nullSafeTrim(ticket.getRemark());
}
public String getTraveler() {
AirTraveler traveler = ticket.getTraveler();
String fullName = traveler.passengerType().name() + Constants.SPACE
+ traveler.fullName();
if (traveler.isInfant()) {
fullName += Constants.SPACE + "(" + traveler.getCarriedBy() + ")";
}
return fullName;
}
public String getDocumentNumber() {
AirTraveler traveler = ticket.getTraveler();
if (traveler.isAdult()) {
return traveler.getDocument().getNumber();
} else if (traveler.isChild() || traveler.isInfant()) {
return DateUtils.format(traveler.getDocument().getDateOfBirth(),
Constants.DEFAULT_DATE_PATTERN);
} else {
return PassengerType.UNKNOWN.name();
}
}
public String getDocumentType() {
return ticket.getTraveler().getDocument().type().name();
}
public String getStatusName() {
return ticket.status().name();
}
public String getTotalAmount() {
Money totalAmount = ticket.getTotalAmount();
return totalAmount.getCurrencySymbol() + totalAmount.getAmount();
}
}
上面的视图适配器旨在
避免在 jsp 上使用 train wreck 代码(在 jsp 上难以重构,当时模型不稳定)
避免在 jsp 上使用 if/else jsplet 代码。我们针对 api 层开发了验收测试(让测试直接与 ui 交互更昂贵),因此任何自动化测试都没有涵盖 jsps。但是,我们为这些 ViewAdapter 编写了单元测试(更便宜)。
我听说过的缺点是
如果有人在将实体传递给 ViewAdapter 后对其进行更新,则第二种解决方案会引入细微的不一致(这是与 .net 相关的帖子,我现在找不到它)
如果您采用委托 getAge() 策略,如果要访问延迟加载属性,则可能存在会话关闭异常。这取决于你的持久性基础设施,当我们使用 iBATIS 时没问题,当我们切换到 Hibernate 时失败,没有额外的分离。
最后但并非最不重要的一点是,应根据您的项目和团队做出决定。我认为没有一种万能的解决方案。
希望这可以帮助 :)