我有一個基於管道的應用程序,它可以分析不同的語言(比如英語和中文)中的文本。我的目標是有一個系統,可以在兩種語言,透明的方式。 注意:這個問題很長,因爲它有很多簡單的代碼片段。管道系統的體系結構/設計。如何改進此代碼?
管道是由三個部分組成(可以稱它們爲A,B,和C),並且我創建他們以下面的方式,從而使組分不緊密耦合的:
public class Pipeline {
private A componentA;
private B componentB;
private C componentC;
// I really just need the language attribute of Locale,
// but I use it because it's useful to load language specific ResourceBundles.
public Pipeline(Locale locale) {
componentA = new A();
componentB = new B();
componentC = new C();
}
public Output runPipeline(Input) {
Language lang = LanguageIdentifier.identify(Input);
//
ResultOfA resultA = componentA.doSomething(Input);
ResultOfB resultB = componentB.doSomethingElse(resultA); // uses result of A
return componentC.doFinal(resultA, resultB); // uses result of A and B
}
}
現在,管道的每個組件都具有特定語言的內容。例如,爲了分析中文文本,我需要一個庫,並且爲了分析英文文本,我需要另一個不同的庫。
此外,還有一些任務可以用一種語言完成,而另一些則無法完成。解決這個問題的一個辦法是將每個管道組件抽象化(實現一些常用方法),然後具體實現具體的語言。與組分A來鳳縣,我有以下幾點:
public abstract class A {
private CommonClass x; // common to all languages
private AnotherCommonClass y; // common to all languages
abstract SomeTemporaryResult getTemp(input); // language specific
abstract AnotherTemporaryResult getAnotherTemp(input); // language specific
public ResultOfA doSomething(input) {
// template method
SomeTemporaryResult t = getTemp(input); // language specific
AnotherTemporaryResult tt = getAnotherTemp(input); // language specific
return ResultOfA(t, tt, x.get(), y.get());
}
}
public class EnglishA extends A {
private EnglishSpecificClass something;
// implementation of the abstract methods ...
}
此外,由於每個管道組件是非常沉重的,我需要重用他們,我想創造一個工廠,對於緩存了組件的進一步使用,使用使用的語言爲重點,像這樣的地圖(其它組件會以同樣的方式工作):
public Enum AFactory {
SINGLETON;
private Map<String, A> cache; // this map will only have one or two keys, is there anything more efficient that I can use, instead of HashMap ?
public A getA(Locale locale) {
// lookup by locale.language, and insert if it doesn't exist, et cetera
return cache.get(locale.getLanguage());
}
}
所以,我問題是:你認爲這個設計是什麼?怎麼可能是改進?我需要「透明度」,因爲語言可以根據正在分析的文本動態更改。正如您從runPipeline
方法中看到的那樣,我首先確定輸入的語言,然後基於此,我需要將管道組件更改爲所標識的語言。因此,而不是直接調用的組件,也許我應該從廠家得到他們,就像這樣:
public Output runPipeline(Input) {
Language lang = LanguageIdentifier.identify(Input);
ResultOfA resultA = AFactory.getA(lang).doSomething(Input);
ResultOfB resultB = BFactory.getB(lang).doSomethingElse(resultA);
return CFactory.getC(lang).doFinal(resultA, resultB);
}
感謝您遠閱讀本。我非常感謝你在這個問題上可以提出的每一個建議。
感謝您的意見和建議!我已經閱讀了關於Builder模式的一些文章,並且如果我正確理解了它,這個想法應該是有一個`PipelineBuilder`,在給定語言的情況下,可以創建組件A,B和C語言特定版本的方法,然後返回一個方法返回「剛建好」的語言特定的「管道」。然後,我會有一個`PipelineEngine`,它將接收一個`Pipeline`並執行`runPipeline`。現在,我的問題是,我將在運行時切換語言/管道,並且每次創建新管道的成本都很高。我如何緩存它們? – 2009-07-21 01:41:07