发布
社区首页 >问答首页 >设计-在执行每个方法之前检查一个条件

设计-在执行每个方法之前检查一个条件
EN

Stack Overflow用户
提问于 2015-08-10 22:38:10
回答 3查看 1.5K关注 0票数 7

我有一个名为Document.java的POJO,带有100+成员变量。有一个转换层,在该层中,我获取所需的数据,将其转换并存储在文档类中。

在转换层中,我只想在满足某个标准(基于可用上下文)的情况下设置一个成员变量。

所以看起来是这样的:

代码语言:javascript
代码运行次数:0
复制
if(shouldGetExecuted1(context.getXXX())){
  document.setField1(tranformDataForField1(availableData1));
}

if(shouldGetExecuted2(context.getXXX())){
  document.setField2(tranformDataForField2(availableData2));
}

我想对所有的100+字段都这样做。有干净的方法吗?

附加信息

我不想在这里使用策略,因为随着策略的增加,它会创建太多的类。

EN

回答 3

Stack Overflow用户

发布于 2015-08-10 23:11:16

尝试使用AOP。AspectJ允许您定义切入点(例如,一些过滤的方法集),并通过建议(在方法调用之前、之后、周围)控制它们的执行:

代码语言:javascript
代码运行次数:0
复制
@Aspect
class ClassName {
...

@PointCut("call(public void ClassName.*(..))") //includes all void methods of ClassName object 
public void myPointCut(){}

@Around("myPointCut()")
public void myLogicMethod(ProceedingJoinPoint thisJoinPoint) {

    if(shouldGetExecuted1(context.getXXX())){
        thisJoinPoint.proceed()
    }
}
}

在这里,thisJoinPoint.proceed()将执行被拦截方法的主体。

阅读有关如何定义切入点的文档。在本例中,同样的逻辑将应用于该类的所有void方法。您可以通过特殊表达式定义更精确的切入点,从而为每个切点提供不同的逻辑。

票数 1
EN

Stack Overflow用户

发布于 2015-08-10 23:03:21

不,在Java中没有干净的方法可以做到这一点。您可以使用反射找到方法,但是无法找到诸如"availableDataN“这样的变量。因此,您必须将"availableDataN“作为一个字段,以便使用反射找到它。

最后的代码将像以下所示的那样丑陋:

代码语言:javascript
代码运行次数:0
复制
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class X {

    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {

            Method shouldGetExecuted = X.class.getMethod("shouldGetExecuted" + i, String.class);
            boolean b = (boolean) shouldGetExecuted.invoke(null, context.getXXX());
            if (b) {
                Method tranformDataForField = X.class.getMethod("tranformDataForField");
                Field data = X.class.getField("availableData" + i); 
                Object result = tranformDataForField.invoke(null, data.get(null));
                Method set = X.class.getMethod("setField" + i, TransformDataType.class);
                set.invoke(null, result);
            }
        }
    }

}

你需要适应你的具体情况。例如,这里假设所有字段和方法都是静态的。如果它们不是,则需要用实例引用替换null。

票数 0
EN

Stack Overflow用户

发布于 2015-08-11 16:25:14

如果您在命名方法时是一致的,那么反射可能会有很大帮助。

以下代码假设如下:

  • 一个Document类,包含像xxxxxYy这样的字段(getter/setter通常会出现,但代码不需要)
  • 一个具有Transformer的类
    • 根据上下文信息确定字段是否应该被处理的能力。这些方法被命名为shouldTransformXxx(context)
    • 转换字段内容的能力(输入和输出类型与Document中的相应字段相同)。这些方法被命名为T transformXxx(T)

  • 具有提供未转换数据的方法的DataProvider类。这些方法被命名为findXxx()

下面的代码是非常乐观的--如果任何字段的shouldTransformXxx失败,或者如果它返回true,则findXxxtransformXxx方法也会失败。因此,您必须创建每个方法都有100个方法的类,这对我来说似乎不太理想。但另一方面,拥有100名成员的班级似乎会导致尴尬的局面。

下面是代码:

代码语言:javascript
代码运行次数:0
复制
public class Document {
    private String name;
    private int size;

    @Override
    public String toString() {
        return "Document [name=" + name + ", size=" + size + "]";
    }
}

public class Transformer {
    public enum ContextType {
        NAME, SIZE
    }

    public boolean shouldTransformName(Set<ContextType> context) {
        return context.contains(ContextType.NAME);
    }

    public boolean shouldTransformSize(Set<ContextType> context) {
        return context.contains(ContextType.SIZE);
    }

    public String transformName(String name) {
        return "::" + name;
    }

    public int transformSize(int size) {
        return size + 1;
    }
}

public class DataProvider {
    private final String name;
    private final int size;

    public DataProvider(String name, int size) {
        this.name = name;
        this.size = size;
    }

    public String findName() {
        return name;
    }

    public int findSize() {
        return size;
    }
}

public class Main {

    private static final String TRANSFORM_METHOD_PREFIX = "transform";
    private static final String CHECK_METHOD_PREFIX = "shouldTransform";
    private static final String DATAPROVIDER_METHOD_PREFIX = "find";

    private final DataProvider dataProvider;
    private final Transformer transformer;

    public Main(DataProvider dataProvider, Transformer transformer) {
        this.dataProvider = dataProvider;
        this.transformer = transformer;
    }

    public Document transformFields(Set<ContextType> context)
            throws ReflectiveOperationException {
        Document document = new Document();

        for (Field field : Document.class.getDeclaredFields()) {

            String capitalizedfieldName = capitalize(field.getName());
            Class<?> fieldType = field.getType();

            if (shouldTransform(context, capitalizedfieldName)) {

                Object data = findData(capitalizedfieldName);
                Object transformed = transformData(capitalizedfieldName,
                        fieldType, data);

                // in presence of a security manager, a reflective call of the
                // setter could be performed
                field.setAccessible(true);
                field.set(document, transformed);
            }
        }

        return document;
    }

    private Object transformData(String capitalizedfieldName,
            Class<?> fieldType, Object data)
            throws ReflectiveOperationException {

        String methodName = TRANSFORM_METHOD_PREFIX + capitalizedfieldName;
        Method method = Transformer.class.getMethod(methodName, fieldType);
        return method.invoke(transformer, data);
    }

    private Object findData(String capitalizedfieldName)
            throws ReflectiveOperationException {

        String methodName = DATAPROVIDER_METHOD_PREFIX + capitalizedfieldName;
        Method method = DataProvider.class.getMethod(methodName);
        return method.invoke(dataProvider);
    }

    private boolean shouldTransform(Set<ContextType> context,
            String capitalizedfieldName) throws ReflectiveOperationException {

        String methodName = CHECK_METHOD_PREFIX + capitalizedfieldName;
        Method method = Transformer.class.getMethod(methodName, Set.class);
        return (Boolean) method.invoke(transformer, context);
    }

    private String capitalize(String fieldName) {
        char upperCaseFirstChar = Character.toUpperCase(fieldName.charAt(0));

        if (fieldName.length() > 1) {
            return upperCaseFirstChar + fieldName.substring(1);
        } else {
            return Character.toString(upperCaseFirstChar);
        }
    }

    public static void main(String[] args) throws ReflectiveOperationException {
        DataProvider dataProvider = new DataProvider("sample", 1);
        Set<ContextType> context = EnumSet.of(ContextType.NAME,
                ContextType.SIZE);

        Main main = new Main(dataProvider, new Transformer());
        Document document = main.transformFields(context);

        System.out.println(document);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31930321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档