如果使用继承并将所有公共代码和属性放入Base类,则可以轻松地在Action类之间共享代码。作为最佳实践,我认为经验法则是prefer composition over inheritance。不过,我发现将这个概念应用于Action类非常困难。也许我做得不对。
例如,我有3个不同的Action类。它们都处理用户可以注册的不同方式(用户可以从多个表单注册)它们最终都调用相同的服务方法,并且需要以相同的方式处理错误。常用代码类似于:
public class RegisterAction1 {
public String execute() {
...Leaving out code here....
try {
registrationService.register(user);
} catch (BusinessException e) {
if(e.getErrors().containsKey("someError3)){
return "Case1";
}
else if (e.getErrors().containsKey("someError1")) {
session.put(Constants.SESSION_REGISTERVO, registerVO);
return "Case2";
} else if(e.getErrors().containsKey("someError2")) {
this.addFieldError("aliasName", this.getText("some.error"));
} else if(ce.getErrors().containsKey("someError3")) {
this.someFieldThatMustBeSetForView1 = true;
this.someFieldThatMustBeSetForView2 = true;
this.addFieldError("addressLine1", null);
this.addFieldError("addressLine2", null);
this.addFieldError("city", null);
}
}
...Leaving out code here....
return "Success";
}
}
要使用合成,我认为您可以将这段逻辑移动到“Helper”类中,并在Action类中引用该Helper。如果你在这个实现这个公共代码的帮助器类中创建一个“callService”方法,你将如何处理这样一个事实,即很多代码实际上正在修改类中的字段...即,你是否传递了一个引用如下所示对辅助方法的动作?如果是这样,你如何处理它可能是三个不同动作类中的一个(即RegisterAction1,RegisterAction2,RegisterAction3)的事实?
public String callService(RegisterAction1 registerAction) {
答案 0 :(得分:2)
有很多方法可以做到。
如果存在需要修改操作数据的非操作类,我可能会选择ModelDriven
方法,并让模型传递,将其与S2体系结构分离(假设您的操作扩展{ {1}})。
在你的情况下,你也直接修改了字段错误(这只是一个地图)。天真(也可能是足够好)的方法是要么只是传递它,要么传递返回可用于修改字段错误的东西,无论是在拦截器中,还是在基本动作类方法。或者,如下面的选项所示,假设访问ActionSupport
impl(以及模型或ValidationAware
impl)。
另一种选择是将相关部分封装在接口中,因此传递给帮助程序的唯一选择是接口实现。如果您想直接访问字段错误地图,还可以包含ModelDriven
。
这两种解决方案也解决了“不同类型的注册行动”问题,除非它们有很大的不同。如果它们是,我会考虑保持原样 - 不必要地过度设计一些东西是没有意义的。