1

我要实现的想法是,我的程序中有一堆动作/功能。它们都是预定义的并分为几类。因此,可能会有一个管理操作类别,然后为管理操作类别中的操作定义一堆静态代码。

由于类别和动作是固定的,它们都在静态类中。

这些静态类别类都实现了一个接口,ICategory:

public static interface ICategory{
    int getCateogory();
    String getCategoryName();
    String getFunctionName(int function);
}

这些静态类中的每一个都被添加到静态 Map 中:

private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();

基本上每个类别都有一个整数代码。我要做的只是制作一个人类可读的字符串,当我收到类别和操作代码时可以打印出来。我想做的是

ICategory whatever = catMap.get(catNumber);
System.out.println(whatever.getCategoryName());
System.out.println(whatever.getFunctionName(actionCode));

所以 catMap.get(catNumber) 实际上会返回正确的静态类,但是我不知道如何使用返回的类来访问这些静态方法。我可以用一个类的常规实例来做这件事,很好,但是用静态类做这件事让我很困惑。

问题说明:

一些澄清我试图解决的问题,以防你们有更好/更直观的方法建议:

基本上,我正在解释来自我公司的一些定制硬件的命令。这是一个小数据收集小玩意儿,有一堆我必须解释的预定义消息/功能。

这些功能分为不同的类别:显示、键盘、采集等。

所以基本上我有一个这样的映射:

  Display Category: 128
      ShowGraph: 01
      ShowText: 02
  Keypad Category: 129
      F1: 01
      F2: 02
      MenuKey: 03

我正在制作一个小流显示,以人类可读的格式打印命令流。所以我只是打印出一个大列表,比如

Got Category Display, Function ShowGraph
Got Category Keypad, Function MenuKey

通常我会为此使用映射,但我想要的是将每个类别中的函数也用作常量,因为我必须在 if 语句中引用它们,并且经常将这些相同的类别发送回小 gizmo。

例如:

sendMessage(Categories.DisplayCategory.getCategoryInt(), Categories.DisplayCategory.SHOW_GRAPH);

根据要求提供更多代码:

public class Functions {

    public static interface ICategory{
        int getCateogory();
        String getCategoryName();
        String getFunctionName(int function);
    }

    private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();

    public static String getCategoryString(int category) {
        Class<? extends ICategory> clazz = catMap.get(category);
        System.out.println(catMap.toString());

        if(clazz != null){
            try{
                Method m = clazz.getMethod("getCategoryName", Integer.class);
                return (String) m.invoke(0, category);
            }catch (Exception e){
                return null;
            }

        }else{
            System.out.println("clazz was null");
            return null;
        }
    }

    public static class SystemKey implements ICategory{
        public static int CATEGORY = 134;
        private static Map<Integer, String> fmap = new HashMap<Integer, String>();
        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "SystemKey";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }
    }

    public static class SystemCat implements ICategory{
        public static int CATEGORY = 128;
        private static Map<Integer, String> fmap = new HashMap<Integer, String>();

        public static final int POWER_UP = 0x01;
        public static final int END_OF_TRANSMIT = 0x02;
        public static final int CLEAR_TO_SEND = 0x03;
        public static final int NET_TEST = 0x05; /*Fom station to ctrlr*/ 
        public static final int NET_OK = 0x06; /*Response to controller*/
        public static final int MAIN_MENU = 0x07;

        static{
            catMap.put(CATEGORY, SystemCat.class);

            fmap.put(POWER_UP, "POWER_UP"); 
            fmap.put(END_OF_TRANSMIT, "END_OF_TRANSMIT"); 
            fmap.put(CLEAR_TO_SEND, "CLEAR_TO_SEND");
            fmap.put(NET_TEST, "NET_TEST"); 
            fmap.put(NET_OK, "NET_OK"); 
            fmap.put(MAIN_MENU, "MAIN_MENU");
        }


        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "System";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }
    }




    public static class SoftKey implements ICategory{
        public static int CATEGORY = 129;

        private static Map<Integer, String> fmap = new HashMap<Integer, String>();

        public static final int F1 = 0x20;
        public static final int F2 = 0x21;
        public static final int F3 = 0x22;
        public static final int F4 = 0x23;
        public static final int F5 = 0x24;

        static{
            catMap.put(CATEGORY, SoftKey.class);

            fmap.put(F1, "F1");
            fmap.put(F2, "F2");
            fmap.put(F3, "F3");
            fmap.put(F4, "F4");
            fmap.put(F5, "F5");

        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "SoftKey";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }

    }


    public static void main (String[] args) throws Exception{


         System.out.println(Functions.getCategoryString(128));
    }

}
4

2 回答 2

1

更新

正如我所怀疑的,解决方案非常简单。有不同的方法可以做到这一点,这里有一种,我似乎记得叫它Registry,早在模式被称为 Idioms 的日子里。您快到了,您需要进行以下更改:

  1. catMap将类型从更改Map<String,Class<? extends ICategory>Map<Integer, ICategory>

  2. static initializers创建一个对象并将其放入地图中,例如

    公共静态类 SoftKey 实现 ICategory{ ....

    static{
        catMap.put(CATEGORY, new SoftKey());
    
  3. getCategoryString使用ICategory注册表中的对象:

    ICategory 类别 = catMap.get(category); 返回categ.getCategoyString()


我可能误解了这个问题,但其中一部分令人困惑:

所以 catMap.get(catNumber) 实际上会返回正确的静态类,

static class我假设您的意思interfaces是嵌套在某个类/接口中。Java 中没有顶级静态类。 get返回 aObject的 a static class,而不是 a class

但是我不知道如何使用返回的类来访问这些静态方法。

您声明的方法不是static,它们是instance methods

我可以用一个类的常规实例来做这件事,很好,但是用静态类做这件事让我很困惑。

我也很纳闷。您可以在静态类的对象上调用实例方法。你能发布一个完整的代码示例吗?

于 2013-05-14T00:31:46.207 回答
1

假设您事先知道所有代码,并且没有 1000 个函数值,这将起作用。只要您不介意通过容器查找它们(而不是 Map),函数值代码的非唯一性就不是问题。

如果您不介意一直循环遍历所有枚举值,则可以完全取消静态映射。如果您不经常进行查找,这可能是完全可以接受的。

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public enum FunctionCategory {

    DISPLAY(128, "Display"),
    KEYPAD(129, "KeyPad");
    // more categories here...
    private final int code;
    private final String name;

    private static Map<Integer, FunctionCategory> categoryMap = new HashMap<>();

    static {
        for( FunctionCategory c : FunctionCategory.values() ) {
            categoryMap.put(c.getCode(), c);
        }
    }

    // For looking up a category from its code
    public static FunctionCategory fromCode( int code ) {
        return categoryMap.get(code);
    }

    private FunctionCategory(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public String getName() {
        return name;
    }


    public static enum FunctionValue {

        // DISPLAY
        DISPLAY_GRAPH(DISPLAY, 1, "Graph"),
        DISPLAY_TEXT(DISPLAY, 2, "ShowText"),
        //KEYPAD
        KEYPAD_MENU(KEYPAD, 1, "MenuKey"),
        KEYPAD_ENTER(KEYPAD, 2, "EnterKey");
            // TODO, others
        private static Map<FunctionCategory, Set<FunctionValue>> codeMapping = new EnumMap<>( FunctionCategory.class );

        static {
            for( FunctionValue fv : FunctionValue.values() ) {
                Set<FunctionValue> values = codeMapping.get(fv.getCategory());
                if( values == null ) {
                    values = EnumSet.of(fv);
                }
                else {
                    values.add(fv);
                }
                codeMapping.put(fv.getCategory(), values);
            }
        }

            // First we look up the category, then we just loop over all the values
            // within that category. Unless you have lots of values, or really need
            // to optimize the lookups, there is no need to do something more complex
        public static FunctionValue getFromCodes( int categoryCode, int valueCode ) {
            FunctionCategory c = FunctionCategory.fromCode(categoryCode);
            if( c != null ) {
                Set<FunctionValue> valueSet = codeMapping.get(c);
                if( valueSet != null ) {
                    // Just spin through them, there aren't that many
                    for( FunctionValue v : valueSet ) {
                        if( v.getCode() == valueCode ) {
                            return v;
                        }
                    }
                }
            }
            return null;
        }

        private final FunctionCategory category;
        private final int code;
        private final String name;
        private FunctionValue(FunctionCategory category, int code, String name) {
            this.category = category;
            this.code = code;
            this.name = name;
        }
        public FunctionCategory getCategory() {
            return category;
        }
        public int getCode() {
            return code;
        }
        public String getName() {
            return name;
        }       
    }
}
于 2013-05-14T02:29:49.477 回答