标记方法并通过标记从客户端对象调用它们

den*_*chr 5 java oop methods design-patterns switch-statement

我一直试图找到一种方法来从我的基类中标记几个方法,以便客户端类可以通过标记来调用它们.示例代码是:

public class Base {
         public void method1(){     
        ..change state of base class
    }

    public void method2(){      
        ..change state of base class
    }

    public void method3(){      
        ..change state of base class
    }
}
Run Code Online (Sandbox Code Playgroud)

main()方法的客户端类将通过随机指令序列调用Base的每个方法:

public static void main(String[] args) {
String sequence = "ABCAABBBABACCACC"
Base aBase = new Base();
for (int i = 0; i < sequence.length(); i++){
            char temp = sequence.charAt(i);
            switch(temp){
            case 'A':{aBase.method1(); break;}
            case 'B':{aBase.method2(); break;}
            case 'C':{aBase.method3(); break;}          }
        }

        System.out.println(aBase.getState());

    }
Run Code Online (Sandbox Code Playgroud)

现在我希望从Client对象中完全摆脱switch语句.我知道通过多态替换switch的技术,但是想避免创建一组新类.我希望简单地将这些方法存储在适当的数据结构中,并以某种方式用序列中的匹配字符标记它们.

地图可以轻松地存储具有值/键对的对象,这些对象可以完成工作(如我在此处所做)或命令模式,但由于我不想用对象替换这些方法,可能有不同的方法,存储方法并让客户有选择地调用它们?

任何建议表示赞赏

ska*_*man 6

像这样的东西?

public class Base {

    private final Map<Character, Method> methods = new HashMap<Character, Method>();

    public Base() throws SecurityException, NoSuchMethodException {
        methods.put('A', getClass().getMethod("method1"));
        methods.put('B', getClass().getMethod("method2"));
        methods.put('C', getClass().getMethod("method3"));
    }

    public Method getMethod(char c) {
        return methods.get(c);
    }

    public void method1() {}

    public void method2() {}

    public void method3() {}

}
Run Code Online (Sandbox Code Playgroud)

然后

    public static void main(String[] args) throws Exception {
        String sequence = "ABCAABBBABACCACC";
        Base aBase = new Base();

        for (int i = 0; i < sequence.length(); i++) {
            char temp = sequence.charAt(i);
            aBase.getMethod(temp).invoke(aBase);
        }
    }
Run Code Online (Sandbox Code Playgroud)


And*_*yle 5

我会对有问题的方法使用注释,允许它被标记为"标记方法",并提供用于该方法的标记字符串.

从那时起,实现变得更加简单; 你可以使用反射来迭代类的方法并检查它们的注释; 也许在启动时静态地执行此操作并填充从标记字符串到java.lang.reflect.Method的映射.

然后在处理命令字符串时,调用与每个标记对应的方法.

编辑:一些示例代码:

import java.lang.annotation.*; 

@Retention(RetentionPolicy.RUNTIME)
@interface TaggedMethod {
    String tag();
}
Run Code Online (Sandbox Code Playgroud)

然后在基类中:

public class Base {

   @TaggedMethod(tag = "A")
   public void method1(){         
    ..change state of base class
   }

   @TaggedMethod(tag = "B")
   public void method2(){              
    ..change state of base class
   }

   @TaggedMethod(tag = "C")
   public void method3(){              
    ..change state of base class
   }
}
Run Code Online (Sandbox Code Playgroud)

......并在客户端:

private static final Map<String, Method> taggedMethods = new HashMap<String, Method>();

// Set up the tag mapping
static
{
   for (Method m : Base.class.getDeclaredMethods())
   {
      TaggedMethod annotation = m.getAnnotation(TaggedMethod.class)
      if (annotation != null)
      {
         taggedMethods.put(annotation.tag(), m);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

以便您可以访问:

public static void main(String[] args) throws Exception
{
   String sequence = "ABCAABBBABACCACC"
   Base aBase = new Base();
   for (int i = 0; i < sequence.length(); i++)
   {
            String temp = sequence.substring(i,1);
            Method method = taggedMethods.get(temp);
            if (method != null)
            {
                // Error handling of invocation exceptions not included
                method.invoke(aBase);
            }
            else
            {
               // Unrecognised tag - handle however
            }
    }

    System.out.println(aBase.getState());

}
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这段代码还没有编译或测试...... :-)