我想要的想法是我的程序中有一堆动作/功能。它们都是预定义的并分为几类。因此,管理员操作可能会有一个类别,然后为管理操作类别中的操作定义一堆静态代码。
由于类别和操作是固定的,因此它们都是静态类。
这些静态类别类都实现了一个接口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语句中引用它们,并且经常将这些相同的类别发送回小小发明。
For Instance:
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));
}
}
答案 0 :(得分:1)
我怀疑,解决方案非常简单。有不同的方法可以做到这一点,这里有一个,我似乎记得称之为Registry
,回到模式被称为习语的时代。你几乎就在那里,你需要的是跟随变化:
将catMap
类型从Map<String,Class<? extends ICategory>
更改为Map<Integer, ICategory>
。
在static initializers
创建一个对象并将其放入地图中,例如
public static class SoftKey实现ICategory { ....
static{
catMap.put(CATEGORY, new SoftKey());
在getCategoryString
中使用注册表中的ICategory
对象:
ICategory categ = catMap.get(category); return categor.getCategoyString()
我可能误解了这个问题,但其中一部分令人困惑:
因此catMap.get(catNumber)实际上将返回正确的静态类
按static class
我假设你的意思是interfaces
嵌套在某个类/接口中。 Java中没有顶级静态类。 get
会返回Object
的 static class
,而不是class
。
但我不知道如何使用返回的类来访问这些静态方法。
您声明的方法不是static
,而是instance methods
我可以用类的常规实例来做,很好,但是使用静态类做这件事让我感到困惑。
我也很困惑。您可以调用静态类对象的实例方法。你能发一个完整的代码样本吗?
答案 1 :(得分: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;
}
}
}