我有一个基于管道的应用程序,它可以分析不同的语言(比如英语和中文)中的文本。我的目标是有一个系统,可以在两种语言,透明的方式。 注意:这个问题很长,因为它有很多简单的代码片段。管道系统的体系结构/设计。如何改进此代码?
管道是由三个部分组成(可以称它们为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