我正在创建一个名为Question
的类。这个类有答案,所以我希望能够返回附加到它的答案列表。
但是,如果用户对答案进行了更改,我希望用户调用更新方法,以便我可以进行其他验证等。如果用户获得答案列表,他现在仍然可以通过说明更改答案question.getAnswers().get(0).setDescription("BLAH BLAH").
所以我想回复每个答案的副本,让用户改变这个,他必须将它合并/更新回问题。通过这种方法,我可以确保答案是有效的,但答案的等于方法基于description
和correct
字段而不是id
字段,因为我使用JPA。如果用户使用这种方法更改答案,则更新方法将找不到答案,因为描述字段已更改且不再相等,因此它在列表中找不到它。
有任何建议吗?
public void updateAnswer(Answer answer) {
int index = answers.indexOf(answer);
answers.set(index, answer);
}
public List<Answer> getAnswers() {
return Collections.unmodifiableList(answers);
}
@Test
public void shouldUpdateAnswerInQuestion() {
// Get first answer, make an update on the description
// and then update answer on question.
Answer answerThatWillBeUpdated = question.getAnswers().get(0);
String updatedAnswerDescription = "Hey, it is now updated!";
answerThatWillBeUpdated.setDescription(updatedAnswerDescription);
question.updateAnswer(answerThatWillBeUpdated);
// After updating check that the answer in the list is equal
// to the answer updated.
Answer answerFromList = question.getAnswers().get(0);
assertEquals(answerThatWillBeUpdated, answerFromList);
}
答案课:
public class Answer {
private long id;
private String description;
private Boolean correct;
...
}
答案 0 :(得分:1)
你应该重新考虑你的应用程序的设计,但由于我不确定你的域约束总体如何,我不能建议稍微重新设计或任何类型。
一个简单明了的答案是:程序到界面,而不是实现。如果要在修改setter之后强制调用update方法,请考虑使用Decorator模式。
然后你只需将所有方法委托给内部实例,并将你想要调用的方法委托给update,就这样做:
public void setField(int a){ innerInstance.setField(一); 更新(...); }
答案 1 :(得分:0)
为什么不在更新方法中使用id字段进行比较?当您向用户提供答案对象的副本时,请确保您的副本具有与当前答案对象相同的ID。因此,当用户更改答案时,您的更新验证代码仍然可以根据ID字段找出已更改的答案。
答案 2 :(得分:0)
一般来说,我知道2个解决方案。
返回列表的深层副本而不是源列表。在这种情况下,用户在答案描述中所做的任何更改都不会产生任何影响。 从性能和内存利用的角度来看,这个解决方案很简单但效果很差。它也不是用户友好的。当用户尝试执行受限操作时,良好的API应该抛出异常。
其他解决方案是返回不可修改对象的列表,即当用户尝试调用其setter时抛出异常的对象。
此解决方案有几种可能的实现方式。
2.1。修改模型类的setter。如果以只读模式创建对象,则所有setter都应该能够抛出异常。
2.2。用户包装(装饰)模式。
2.2.1。为所有值对象创建接口,并为每个类实现包装器。例如,AnswerWrapper将实现接口Answer,保持在Answer类型的包装对象内,将除setters之外的所有方法委托给该对象的适当方法,并从每个setter中抛出异常。
2.2.2。使用动态代理技术。您仍然需要接口,但不必为所有类实现所有setter。此解决方案类似于方面。
2.3。使用方面。例如AspectJ。
答案 3 :(得分:0)
客户端代码具有列表,因此它知道列表索引,让它告诉您要更新哪一个:
public void updateAnswer(int index, Answer newAnswer) {
answers.set(index, answer);
}
// ...
Answer answerThatWillBeUpdated = question.getAnswers().get(0);
String updatedAnswerDescription = "Hey, it is now updated!";
answerThatWillBeUpdated.setDescription(updatedAnswerDescription);
question.updateAnswer(0,answerThatWillBeUpdated);