2014-09-02 83 views
3

我想實現一個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 = "123456789"; 
    String field2 = "12345" + FNC1; 

    String id2 = "00"; 
    String field3 = "123456789"; 

    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 
     } 
     .... 
    } 
    } 
} 

解析器返回標識符值,驗證其長度並且該值具有正確的字符類型(數字或字母數字)。 這個設計的問題是,當第一次被調用時,它會創建數百個新對象(每個標識符和它的解析器)。大多數時候條形碼只有3或4個標識符。所以,我認爲這是時間和記憶的一種滋味。我搜索解析器的「懶惰inizialitation」設計,但我還沒有找到與我的問題相對應的東西。有更好的設計嗎?或者我的擔心是沒有用的。

謝謝

回答

1

我認爲你可以保持enum方法。但要利用枚舉Singleton特性。這意味着你只需要和INSTANCE枚舉值。在你的枚舉中,你保存了一個hashmap,代碼是key。由於您的方法使用代碼作爲輸入。看到這一點:

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作爲一個枚舉,如果你想懶惰初始化它。它應該是一個由我提供代碼的「枚舉緩存」初始化的對象。

編輯2:由Mike Strobel在評論中提出的代碼修改。

+0

那麼「存儲」映射中的值實際上會被讀取和返回嗎? 'search'方法是否只返回'INSTANCE'? – 2014-09-02 14:37:15

+0

使用地圖存儲解析器對象似乎是一個好主意,我只有兩個Parser對象的對象實例。但它是否安全?正如馬特所說,我沒有看到如何從搜索方法中獲得標識符。 – user1151816 2014-09-02 15:04:46

+0

請參閱我的文章的編輯。我澄清了搜索功能中的邏輯。因此,如果代碼包含在地圖中,則返回所需的內容,否則將其初始化。對於線程安全來說,鎖現在保護對hashmap的訪問。 – Esquive 2014-09-02 15:18:35

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); 
    } 
} 
0

謝謝您的回答。考慮到他們之後,我決定繼續枚舉設計,但在每個標識符中添加HashMap Matt的建議和解析器的惰性初始化。因此,代碼如下所示:

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(); 
} 
+0

很高興您找到您感覺舒適的東西。如果您想要點擊答案旁邊的複選標記,請隨時「接受」答案。 (如果你願意的話,你甚至可以接受你自己的。)如果你有足夠的聲望,你也可以提出任何有助於對話的答案。 – 2014-09-08 21:58:29