验证输入并相应地执行操作

时间:2016-12-19 19:54:25

标签: java validation design-patterns

我有两个程序需要在几个字段上进行验证。

  • 对于ProcessA课程,我需要在几个字段上进行验证。根据这些领域,我将验证这门课程。
  • 对于ProcessB课程,我需要在不同的字段上进行验证。如果这些字段有效,那么我将验证这个类。

我的流程都应该将GenericRecord传递给Validator类,现在取决于它是ProcessA还是ProcessB,我的Validator类应验证这些字段

  • 对于ProcessA,我需要在clientIddeviceIdpayId上进行验证。
  • 对于ProcessB,我需要在crossIdmaxIdminId上进行验证。

我能够使其适用于ProcessA,但我很困惑Validator类对ProcessB字段验证的看法。困惑是Validator类在构造函数中收到GenericRecord后,如何确定我需要验证ProcessA或ProcessB的字段。如果传递ProcessA GenericRecord,则对ProcessA字段进行验证或者如果传递ProcessB GenericRecord,则在ProcessB字段上进行验证。

ProcessA

try {
  GenericRecordDomainDataDecoder decoder = new GenericRecordDomainDataDecoder(config);
  while (true) {
    ConsumerRecords<byte[], byte[]> records = consumer.poll(1000);
    for (ConsumerRecord<byte[], byte[]> record : records) {
      GenericRecord payload = decoder.decode(record.value());
      String processName = "processA";
      // validation logic
      Validator validation = new Validator(payload);
      if(!validation.isValid())
          continue;

      // some other code
    }
  }
} catch (Exception ex) {
  // logging error
}

进程B

try {
  GenericRecordDomainDataDecoder decoder = new GenericRecordDomainDataDecoder(config);
  while (true) {
    ConsumerRecords<byte[], byte[]> records = consumer.poll(1000);
    for (ConsumerRecord<byte[], byte[]> record : records) {
      GenericRecord payload = decoder.decode(record.value());
      String processName = "processB";
      // validation logic
      Validator validation = new Validator(payload);
      if(!validation.isValid())
          continue;

      // some other code
    }
  }
} catch (Exception ex) {
  // logging error
}

以下是我的Validator类,它现在只适用于ProcessA验证。我添加了另一个构造函数,我知道它不起作用,但只是想展示我想要为ProcessB做些什么。然后我需要调用isValid方法来告诉我ProcessB的字段是否存在。

public class Validator {
  private String clientId, deviceId, payId;

  // for ProcessA
  public Validator(GenericRecord payload) {
    clientId = (String) DataUtils.parseRecord(payload, "clientId");
    deviceId = (String) DataUtils.parseRecord(payload, "deviceId");
    payId = (String) DataUtils.parseRecord(payload, "payId");
  }

  // for ProcessB, I know this doesn't work - just wanted to show the idea
  public Validator(GenericRecord payload) {
    crossId = (String) DataUtils.parseRecord(payload, "crossId");
    maxId = (String) DataUtils.parseRecord(payload, "maxId");
    minId = (String) DataUtils.parseRecord(payload, "minId");
  }

  // this is what I am calling for ProcessA
  public boolean isValid() {
    return isValidClientIdDeviceId() && isValidPayId();
  }

  private boolean isValidPayId() {
    if (payId == null) {
      logger.log("invalid payId.");
      return false;
    }
    return true;
  }

  private boolean isValidClientIdDeviceId() {
    if (clientId == null && deviceId == null) {
      logger.log("invalid clientId and deviceId.");
      return false;
    }
    return true;
  }

  // getters
}

我可以将另一个参数processName传递给Validator类。我们可以使用它来实现这一点来相应地验证字段。

1 个答案:

答案 0 :(得分:1)

如果您的Process类型很少,我建议您使用的第一个解决方案。

您可以拥有一个空构造函数,并在构造函数之后通过Process调用一个init方法。

只需保留默认构造函数(不需要声明):

  public Validator() {   
  }

  // for ProcessA
  public initProcessA(GenericRecord payload) {
    clientId = (String) DataUtils.parseRecord(payload, "clientId");
    deviceId = (String) DataUtils.parseRecord(payload, "deviceId");
    payId = (String) DataUtils.parseRecord(payload, "payId");
  }

  // for ProcessB, 
  public void initProcessB(GenericRecord payload) {
    crossId = (String) DataUtils.parseRecord(payload, "crossId");
    maxId = (String) DataUtils.parseRecord(payload, "maxId");
    minId = (String) DataUtils.parseRecord(payload, "minId");
  }

在流程A中:

   Validator validation = new Validator();
   validation.initProcessA(payload);  

在流程B中:

   Validator validation = new Validator();
   validation.initProcessB(payload);

这第一个解决方案有其局限性。
如果您具有依赖于Process类的验证特性,则更好的解决方案是使用针对每个进程的不同验证器类来爆炸规则,因为它更易于维护。

你可以拥有例如:

public abstract class Validator<T extends Process>{

   ...
   // common and abstract methods    
   ...
   public abstract boolean isValid();
}

进程A的验证器A:

public class ValidatorA extends Validator<ProcessA>{
   ...
        public ValidatorA(GenericRecord payload){
           clientId = (String) DataUtils.parseRecord(payload, "clientId");
           deviceId = (String) DataUtils.parseRecord(payload, "deviceId");
           payId = (String) DataUtils.parseRecord(payload, "payId");
        }

       public  boolean isValid(){
           // validation rules specific to ProcessA
       }
    ...

}

进程B的验证器B:

public class ValidatorB extends Validator<ProcessB>{
   ...
      public ValidatorB(GenericRecord payload) {
         crossId = (String) DataUtils.parseRecord(payload, "crossId");
         maxId = (String) DataUtils.parseRecord(payload, "maxId");
         minId = (String) DataUtils.parseRecord(payload, "minId");
      }

      public  boolean isValid(){
          // validation rules specific to ProcessB
      }

   ...
}