Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
设计问题-java-实现这一点的最佳方法是什么?_Java_Oop - Fatal编程技术网

设计问题-java-实现这一点的最佳方法是什么?

设计问题-java-实现这一点的最佳方法是什么?,java,oop,Java,Oop,我有一个设计问题 我有两个数据对象,它们是类A和类B的实例。 A和B没有任何行为——它们是带有getter和setter的Javabean。 我有一个验证接口和10个定义不同验证的实现。 我想在我的属性文件中指定哪个验证应用于哪个类。 大概是这样的: A类XYZ验证,ABC验证 B类:ABC验证、PPV验证等 我如何编写我的验证类,以便它服务于类A或类B的实例,或者我将来可能要添加的任何其他类C的实例 interface Validation { public boolean check(?

我有一个设计问题

我有两个数据对象,它们是类A和类B的实例。 A和B没有任何行为——它们是带有getter和setter的Javabean。 我有一个验证接口和10个定义不同验证的实现。 我想在我的属性文件中指定哪个验证应用于哪个类。 大概是这样的:

A类XYZ验证,ABC验证

B类:ABC验证、PPV验证等

我如何编写我的验证类,以便它服务于类A或类B的实例,或者我将来可能要添加的任何其他类C的实例

interface Validation {
public boolean check(??);
}

>我只想加上这句话,向所有回复这篇文章的人表示感谢,并说我很喜欢在这个令人惊叹的网站上度过的时光。堆积如山的岩石

您是否考虑过使用注释来标记要在bean中验证的字段

如果有10个不同的验证,可以指定10个注释。然后使用注释标记字段:

@ValideStringIsCapitalCase
private String myString;

@ValidateIsNegative
private int myInt;
使用反射API遍历所有字段并查看它们是否已标记,如下所示:

public static <T> validateBean(T myBean) throws IllegalAccessException {
    Field[] fields = myBean.getClass().getDeclaredFields();
    // This does not take fields of superclass into account
    if (fields != null) {
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ValideStringIsCapitalCase.class)) {
                field.setAccessible(true);
                Object value = field.get(existingEntity);
                // Validate
                field.setAccessible(false);
            }
        }
    }
}
用于注释界面


EDIT2:请不要直接修改字段(如上面的示例所示)。相反,使用反射访问他们的getter和setter。

我可能误解了这个问题,但这样就足够了:

public class ValidationMappings {
    private Map<Class, Class<Validation>[]> mappings = new HashMap<Class, Class<Validation>[]>();

    public ValidationMappings() {
            mappings.put(A.class, new Class[]{XYZValidation.class, ABCValidation.class});
            mappings.put(B.class, new Class[]{ABCValidation.class, PPPValidation.class});
    }

    public Class[] getValidators(Class cls) {
            if (!mappings.containsKey(cls)) return new Class[]{};
            return mappings.get(cls);
    }
}
公共类验证映射{
私有映射=新的HashMap();
公共验证映射(){
put(A.class,新类[]{XYZValidation.class,ABCValidation.class});
put(B.class,新类[]{ABCValidation.class,PPPValidation.class});
}
公共类[]getValidators(类cls){
if(!mappings.containsKey(cls))返回新类[]{};
返回mappings.get(cls);
}
}

当您想要获取特定类的验证器列表时,您可以调用getValidators(类cls)并迭代每个验证器,为每个验证器创建一个实例,然后调用您的检查方法。

可能是这样的吗

interface Validation {
   public boolean check(Validatable x);
}

interface Validatable {
}


class A implements Validatable {
  ...
}

class Validator {
   public boolean validateObject(Validatable x){
      boolean validated = true;
      ... //read config file, check which validation classes to call
      //for each validation class v in the config file:
          if(!v.check(x)) validated = false;
      return validated;
   }
}

若你们只想让它处理任何对象,那个么它就是你们的接口

interface Validator {
    boolean isValid(Object object);
}
公共布尔检查(对象o)

除非您想使用一些标记接口来标记适合验证的类,否则您的意思是:

public interface Validation<T> {
    boolean check(T object)
}
公共接口验证{
布尔检查(T对象)
}

首先,我将使用以下界面

interface Validator {
    boolean isValid(Object object);
}
隐式记录返回值的实际含义

第二,我建议在接口中记录如果验证器不知道如何处理给定实例,预期的行为

interface Validator {
    /**
     * @return false if this validator detects that the given instance is invalid, true if the given object is valid or this Validator can't validate it.
     */
    boolean isValid(Object object);
}
这样,您就可以简单地拥有一个验证器列表,您可以向其抛出对象

如果不兼容验证器的实现正确(例如,使用早期instanceof),那么它们对性能的影响应该可以忽略不计

另一方面,我会使用一个验证器列表而不是一个集合,这样您就可以根据复杂性对它们进行排序。将便宜的(性能方面的)验证器作为优化放在列表的开头

然后可以使用一段通用代码进行验证,例如

public class Validators {
    public static boolean isValid(Object o, Collection<Validator> validators) {
        for(Validator current : validators) {
            if(!current.isValid()) return false;
        }
        return true;
    }
}
公共类验证程序{
公共静态布尔值isValid(对象o、集合验证器){
for(当前验证程序:验证程序){
如果(!current.isValid())返回false;
}
返回true;
}
}
根据您的用例,最好在接口中返回与布尔值不同的值。如果您需要有关什么是错误的信息,例如要显示它,您需要返回该信息


在这种情况下,保持上述循环运行可能是一个好主意,这样您将获得所有验证错误,而不仅仅是第一个错误。

访问者模式将解决此问题

调用Visitor Validator可以实现以下功能:

public interface Validatable { public boolean validate(Validator v); } public interface Validator { public boolean validate(A a); public boolean validate(B b); } public class A implements Validatable { public boolean validate(Validator v){ return v.validate(this); } } public class B implements Validatable { public void validate(Validator v) { return v.validate(this); } } // Default validator just doesn't know how to // validate neither A's, nor B's public class GenericValidator implements Validator { public boolean validate(A a) { throw new UnsupportedOperationException("Cannot validate A"); } public boolean validate(B b) { throw new UnsupportedOperationException("Cannot validate B"); } } // since XYZValidation is supposed to run only on A's // it only overrides A validation public class XYZValidation extends GenericValidator { public boolean validate(A a) { // validate a return isVAlid(a); } } // since ABCValidation is supposed to run on A's and B's // it overrides A and B validation public class ABCValidation extends GenericValidator { public boolean validate(A a) { // validate a return isVAlid(a); } public boolean validate(B b) { // validate b return isVAlid(b); } } // since ABCValidation is supposed to run only on B's // it overrides A only B validation public class PPPValidation extends GenericValidator { public boolean validate(B b) { // validate b return isVAlid(b); } } 可验证的公共接口{ 公共布尔验证(验证器v); } 公共接口验证程序{ 公共布尔验证(A); 公共布尔验证(B); } 公共类A实现了可验证的{ 公共布尔验证(验证器v){ 返回v.validate(这个); } } 公共类B实现了可验证的{ 公共无效验证(验证程序v){ 返回v.validate(这个); } } //默认验证器只是不知道如何 //既不验证A,也不验证B 公共类GenericValidator实现验证器{ 公共布尔验证(A){ 抛出新的UnsupportedOperationException(“无法验证A”); } 公共布尔验证(B){ 抛出新的UnsupportedOperationException(“无法验证B”); } } //因为XYZValidation应该只在A上运行 //它只覆盖验证 公共类XYZValidation扩展了GenericValidator{ 公共布尔验证(A){ //验证 返回有效(a); } } //因为ABC验证应该在A和B上运行 //它覆盖了A和B验证 公共类ABCValidation扩展了GenericValidator{ 公共布尔验证(A){ //验证 返回有效(a); } 公共布尔验证(B){ //验证b 返回有效(b); } } //因为ABCValization应该只在B上运行 //它只覆盖A和B验证 公共类PPPValidation扩展了GenericValidator{ 公共布尔验证(B){ //验证b 返回有效(b); } }
我也在考虑这个方向,但我喜欢带注释的解决方案。我不喜欢它,因为在check方法中,必须将Validatable强制转换为具体对象。泛型是一个更好、更安全的选择:类验证器{boolean validate(T object);}好吧,我建议将泛型与我的解决方案结合起来:可验证接口是一个人工约束,它不会给你带来任何好处。我错过了一些吗