Enum设计有很多领域

时间:2014-09-02 14:20:08

标签: java enums

我想实现一个EAN128条形码解析器。简而言之,EAN128条形码由一个或多个字段构成,每个字段由字符串标识符和值组成。有一百个不同的标识符,每个值都有固定或可变长度(数字或字母数字)取决于标识符。可变长度值以名为FNC1的特殊字符结尾 我想从条形码中获取所有标识符及其值 我的设计基于枚举,每个代码标识符都有一个字段。

public enum IDENT_EAN128 {
  // Identifier 8003 that has a value composed by 14 numeric chars and 1 to 20 alphanumeric chars
  IDENT_8003 ("8003", FixedParser(14, NUMERIC), VariableParser(20, ALPHANUMERIC)),
  IDENT_00   ("00", FixedParser(18, NUMERIC)),

  .... // hundred identifiers

  private IDENT_EAN128 (String code, Parser... parsers ) {
     ...
  }

  public static IDENT_EAN128 search (String code) {
    // loop IDENT_EAN128.values() to search code identifier
  }
}

public class Main {
  public static void test () {
    String id1 = "8003";
    String field1 = "12345678901234";
    String field2 = "12345" + FNC1;

    String id2 = "00";
    String field3 = "123456789012345678";

    String barcode = id1 + field1 + field2 + id2 + field3;
    for (int posBarcode; posBarcode < barcode.length(); posBarcode++) { // loop chars of barcode
      char[] buffer ...
      IDENT_EAN128 idEAN = IDENT_EAN128.search(buffer)
      if (idEAN != null) {
        // loop Parsers for get identifier value
        // move posBarcode to the first barcode position of next identifier
      }
      ....
    }
  }
}

解析器返回标识符值,验证其长度,并且该值具有正确的char类型(数字或字母数字)。 这种设计的问题在于,当第一次调用它时,它会创建数百个新对象(每个标识符及其解析器)。大多数情况下条形码只有3或4个标识符。所以,我认为这是时间和记忆的结果。我搜索了关于&#34; lazy inizialitation&#34;解析器的设计,但我找不到与我的问题相符的东西。有更好的设计吗?或者我的顾虑是无用的。

由于

3 个答案:

答案 0 :(得分:1)

我认为你可以保持枚举方法。但是要使用枚举Singleton功能。 有了这个,我的意思是你只有和INSTANCE枚举值。在你的枚举中,你保留一个代码作为键的hashmap。由于您的方法使用代码作为输入。见:

public enum IDENT_EAN128_CACHE {

  INSTANCE;

  private static final Map<String, ParserStore> storage = new HashMap<>();

  public synchronized IDENT_EAN128 search (String code) {

    // If the code is already in the map return the needed values 

    // Else lazy initialize the hashmap entries if the requested entry is not contained and return it.

    return 'the value you should return';

    }

}

然后您就可以访问以下功能:

IDENT_EAN128.INSTANCE.search("some code");

修改

使用此设计,如果您想延迟初始化,则无法将IDENT_EAN128保留为枚举。它应该是一个由&#34;枚举缓存&#34;初始化的对象。我提供了代码。

编辑2 :Mike Strobel在评论中提出的代码修改。

答案 1 :(得分:0)

在大多数情况下,你的设计很好,虽然我会使用静态构建的地图进行搜索而不是循环values()。我不担心创建几百个额外对象所涉及的额外内存或CPU周期。它们只针对每个JVM创建一次,所以除非对象是庞大的,或者如果你从1990年开始运行286,否则没什么大不了的。清晰的设计更重要。请注意,我还假设VariableParserFixedParser是类,并在它们前面插入new关键字来调用构造函数。

如果你愿意,你可以懒洋洋地填充codeMap,但这不会给你带来太多帮助。由于已经创建了所有对象,因此您只需在创建Map条目时保存一点点初始化。

public enum IDENT_EAN128 {
    // Identifier 8003 that has a value composed by 14 numeric chars and 1 to 20 alphanumeric chars
    IDENT_8003 ("8003", new FixedParser(14, NUMERIC), new VariableParser(20, ALPHANUMERIC)),
    IDENT_00   ("00", new FixedParser(18, NUMERIC));
    // ... hundred identifiers

    private static final HashMap<String, IDENT_EAN128> codeMap = new HashMap<String, IDENT_EAN128> ();
    static {
        for(IDENT_EAN128 ident: IDENT_EAN128.values()) {
            codeMap.put(ident.getCode(), ident);
        }
    }

    private String code;

    private IDENT_EAN128 (String code, Parser... parsers ) {
        this.code = code;
        // do something with parsers as well...
    }

    public String getCode() {
        return code;
    }

    public static IDENT_EAN128 search (String code) {
        return codeMap.get(code);
    }
}

答案 2 :(得分:0)

感谢您的回答。在考虑它们之后,我决定保留Enumeration设计,但是为每个标识符中的解析器添加了HashMap Matt建议和一个懒惰的inizialitation。所以,代码看起来像这样:

public enum IDENT_EAN128 {
  // Identifier 8003 that has a value composed by 14 numeric chars and 1 to 20 alphanumeric chars
  IDENT_8003 ("8003") {
    @Override public Parser[] getParsers () {
      return new Parser[]{new FixedParser(14, NUMERIC), new VariableParser(20, ALPHANUMERIC)};
    }
  },

  .... // hundred identifiers

  private static final HashMap<String, IDENT_EAN128> codeMap = new HashMap<String, IDENT_EAN128> ();
  static {
    for (IDENT_EAN128 ident: IDENT_EAN128.values())
      codeMap.put(ident.getCode(), ident);
  }

  private IDENT_EAN128 (String code) {
   ...
  }

  public static IDENT_EAN128 search (String code) {
    return codeMap.get(code);
  }

  public abstract Parser[] getParsers ();
}