我遇到了一个相当特殊的设计问题。我使用的是Java ORM,并定义了我的一个模型类,如下所示:
class User extends Model {
// . . .
}
现在,有更多型号,我希望它们都支持数据验证。这个想法很简单:在调用每个setter方法时,内部ArrayList
个错误会不断填充。
现在,所有模型类的错误处理机制完全相同。我可以设想以下界面:
public interface ErrorReportable {
ArrayList<String> errors = new ArrayList<String>();
boolean hasErrors();
ArrayList<String> getErrors();
void resetErrors();
}
现在我遇到了一个问题:所有的方法都是抽象的,这意味着我必须在我的类中为它们提供一个实现。这很难过,因为所有这些方法都将以完全相同的方式实现。理想情况下,这将是我可以巧妙地继承的另一个类,但遗憾的是,Java中没有多重继承。
我的下一个选项是在接口中使用默认方法,但问题是errors
字段,它将变为静态,而我需要每个实例的常规字段。
看起来唯一的解决方案是组合,但是我必须在hasErrors()
上使用User
方法,该方法将return this.error_obj.hasErrors()
。 User::chunk(200, function($users)
{
foreach ($users as $user)
{
//
}
});
。这很好,但在我看来并不是很整洁,因为我不得不两次写东西。
我怎样才能做得更好?
答案 0 :(得分:1)
如果我的需要正确,我会实现一个自己的Model-class,它实现所有neceaasary接口并扩展Model-ancestor,但仍然是Abstract。
然后,所有正常的模型类都从您的抽象模型类继承,以获得接口的实现以及模型类的继承(第二代就是这样)。任何框架检查&#39;实例&#39;对于后来的模型类,它仍然会检查为真。
抽象类甚至不需要任何抽象方法/成员,但它应该保持抽象,以防止从该类直接实例化。
public abstract class myModel extends Model implements ErrorReportable{ ... }
public class User extends myModel { ... }
答案 1 :(得分:1)
我认为模型类最好只公开List<Error> validate()
方法,并且有一个独立的验证器来验证所有字段并收集错误。
这样,收集的消息不是模型状态的一部分,你可以明确控制验证何时发生,你更喜欢组合(这几乎总是一件好事),而且你需要的唯一方法模型类中的实现是特定于实体的验证。
如果您需要添加任何跨字段验证,那么扩展此设计也可以很容易地执行那些与字段验证一起使用。