java—泛型类型接口工厂

disho6za  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(439)

我正在寻找一些帮助,在设计一个通用接口的具体实现工厂。java版本7,不能用8+
给定这样的接口和抽象类:

  1. public interface ValidationStrategy<T> {
  2. String getNativeQuery();
  3. ValidationStrategy<T> withValue(T value);
  4. }
  5. public abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
  6. protected T value;
  7. public void setValue(T value) {
  8. this.value = value;
  9. }
  10. }

我希望有多个这样的接口实现,比如:

  1. public class DocumentValidationStrategy extends AbstractValidationStrategy<String> {
  2. @Override
  3. public String getNativeQuery() {
  4. // here goes customer native query
  5. return null;
  6. }
  7. @Override
  8. public ValidationStrategy<String> withValue(String value) {
  9. setValue(value);
  10. return this;
  11. }
  12. }

这个 ValidationStrategy 将由工厂决定预定义的枚举(接口,必须是跨平台的统一)。这些问题是泛型的,我真的不能绕过它们,我也没有越过任何问题,将解决我的问题

  1. public class ValidationStrategyFactory {
  2. private static final Map<CustomerValueValidationEnum, Class<? extends ValidationStrategy<?>>> validationStrategiesMap = new HashMap<>();
  3. {
  4. validationStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT, DocumentValidationStrategy.class);
  5. }
  6. private static Class<? extends ValidationStrategy<?>> getInstance(CustomerValueValidationEnum validationEnum) {
  7. return validationStrategiesMap.get(validationEnum);
  8. }
  9. public static ValidationStrategy<?> createInstance(CustomerValueValidationEnum validationEnum)
  10. throws IllegalAccessException, InstantiationException {
  11. return getInstance(validationEnum).newInstance();
  12. }
  13. }

这显然会导致一些问题,我无法正确地实现 ValidationStrategy 由于我对java泛型的错误使用,我试图:

  1. public boolean isValueUnique(CustomerValueValidationEnum type, Object value) {
  2. try {
  3. ValidationStrategyFactory.createInstance(type).withValue(value);
  4. } catch (IllegalAccessException | InstantiationException e) {
  5. throw new UnsupportedOperationException();
  6. }
  7. return false;
  8. }

这显然不起作用,因为我不能满足我想要的价值( value 可以是一切,一个 String , Integer 或者 List ). 我知道我正在尝试将工厂模式和策略模式结合起来,并且我尽了最大努力将两者结合起来,我猜这是一个糟糕的模式,但是现在我真的不知道如何创建易于扩展的验证机制,该机制只需要我创建一个类。
编辑:根据请求,在多个服务之间共享的简单枚举类不应包含任何业务逻辑。

  1. public enum CustomerValueValidationEnum {
  2. VALIDATE_DOCUMENT("validateDocumentNumber")
  3. ;
  4. private final String name;
  5. private CustomerValueValidationEnum(String name) {
  6. this.name = name;
  7. }
  8. @ValueMapKey
  9. public String getName() {
  10. return this.name;
  11. }
  12. }
wz3gfoph

wz3gfoph1#

在编译过程中,不可能动态地键入任何泛型类型。我建议您在enum上进行工厂切换(使用或不使用map)。
无Map实施:

  1. enum CustomerValueValidationEnum { // Not provided by OP
  2. VALIDATE_DOCUMENT,
  3. VALIDATE_NUMBER
  4. }
  5. interface ValidationStrategy<T> {
  6. String getNativeQuery();
  7. ValidationStrategy<T> withValue(T value);
  8. }
  9. abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
  10. protected T value;
  11. public void setValue(T value) {
  12. this.value = value;
  13. }
  14. @Override
  15. public String getNativeQuery() {
  16. return null;
  17. }
  18. @Override
  19. public ValidationStrategy<T> withValue(T value) {
  20. setValue(value);
  21. return this;
  22. }
  23. }
  24. class DocumentValidationStrategy<T> extends AbstractValidationStrategy<T> {
  25. @Override
  26. public String getNativeQuery() {
  27. return "Customer Query";
  28. }
  29. }
  30. class ValidationStrategyFactory {
  31. // Generic types are checked during compilation time, can't type it dynamically
  32. public static ValidationStrategy<?> createInstance(CustomerValueValidationEnum validationEnum) {
  33. ValidationStrategy valStrat = null;
  34. switch(validationEnum) {
  35. case VALIDATE_DOCUMENT:
  36. valStrat = new DocumentValidationStrategy<String>();
  37. case VALIDATE_NUMBER:
  38. valStrat = new DocumentValidationStrategy<Integer>();
  39. }
  40. return valStrat;
  41. }
  42. }

使用map实现:

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. enum CustomerValueValidationEnum { // Not provided by OP
  4. VALIDATE_DOCUMENT(String.class),
  5. VALIDATE_NUMBER(Integer.class);
  6. private Class validationType;
  7. CustomerValueValidationEnum(Class cls) {
  8. validationType = cls;
  9. }
  10. public Class getValidationType() {
  11. return validationType;
  12. }
  13. }
  14. interface ValidationStrategy<T> {
  15. String getNativeQuery();
  16. ValidationStrategy<T> withValue(T value);
  17. }
  18. abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
  19. protected T value;
  20. public void setValue(T value) {
  21. this.value = value;
  22. }
  23. @Override
  24. public String getNativeQuery() {
  25. return null;
  26. }
  27. @Override
  28. public ValidationStrategy<T> withValue(T value) {
  29. setValue(value);
  30. return this;
  31. }
  32. }
  33. class DocumentValidationStrategy<T> extends AbstractValidationStrategy<T> {
  34. @Override
  35. public String getNativeQuery() {
  36. return "Customer Query";
  37. }
  38. }
  39. class ValidationStrategyFactory {
  40. private static final Map<Class, ValidationStrategy> validationStrategiesMap = new HashMap<>();
  41. {
  42. validationStrategiesMap.put(String.class, new DocumentValidationStrategy<String>());
  43. validationStrategiesMap.put(Integer.class, new DocumentValidationStrategy<Integer>());
  44. }
  45. private static ValidationStrategy<?> getInstance(CustomerValueValidationEnum validationEnum) {
  46. return validationStrategiesMap.get(validationEnum.getValidationType());
  47. }
  48. }

不能通过使用泛型类型 enum (不实现接口):post
不能动态键入任何泛型类型:post

展开查看全部
6ioyuze2

6ioyuze22#

一种解决方法是使用一种方法来获取每个泛型类型策略,该方法使用一个从单独Map获取的单独方法。
各种策略泛型类型的数量越少,这种方式就越合适。

  1. public class StrategyFactory {
  2. static final Map<CustomerValueValidationEnum, ValidationStrategy<String>> validationStringStrategiesMap = new HashMap<>() {{
  3. validationStringStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT_STRING, new DocumentStringValidationStrategy());
  4. }};
  5. static final Map<CustomerValueValidationEnum, ValidationStrategy<Integer>> validationIntegerStrategiesMap = new HashMap<>() {{
  6. validationIntegerStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT_INTEGER, new DocumentIntegerValidationStrategy());
  7. }};
  8. public static ValidationStrategy<String> stringStrategy(CustomerValueValidationEnum e) {
  9. return validationStringStrategiesMap.get(e);
  10. }
  11. public static ValidationStrategy<Integer> integerStrategy(CustomerValueValidationEnum e) {
  12. return validationIntegerStrategiesMap.get(e);
  13. }
  14. }
  1. public class DocumentStringValidationStrategy extends AbstractValidationStrategy<String> { ... }
  1. public class DocumentIntegerValidationStrategy extends AbstractValidationStrategy<Integer> { ... }

优势:
将始终推断泛型类型: StrategyFactory.integerStrategy(null).withValue(1); 这意味着用户通话非常舒适。
使用较少的泛型类型进行缩放:2个泛型策略->2个Map->2个方法。
缺点:
用户必须知道 String -类型或 Integer -要请求的类型。
不能用大量的泛型类型进行扩展:如果每个策略都有一个自定义类型,那么这个解决方案根本帮不了您。
特点:
非空安全,Map可以返回 null (为了安全行为,我会使用空对象模式)。即使在你们的解决方案中,这也是个问题

展开查看全部

相关问题