一个管道为基础的系统的体系结构/设计。 如何改善这种代码?

我有一个分析不同的语言(如英语和中国)的文本管道的应用程序。 的目标是拥有一个可以在两种工作语言, 透明的方式系统 :这个问题是很长,因为它有很多简单的代码片段。

该管道是由三部分组成(让我们称之为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 } }

现在,管道的每一个部件具有一种内在的东西这是特定的语言。 例如,为了分析中国的文字,我需要lib和分析英文文本,我需要另一种不同的库。

此外,也有一些任务可以在一种语言来完成,而不能在其他实现。 一个解决这个问题的方法是让每个流水线组件抽象(实施一些常用的方法),然后有一个具体的语言特定的实现。 与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); }

感谢您远远阅读。 我非常感谢每一个建议,你可以在这个问题上。

--------------解决方案-------------

本厂想法是好的,因为是这个想法,如果可行的话,封装A,B,C组分到单一类为每种语言。 我会劝你要考虑的一件事是用Interface继承,而不是Class继承。 然后,您可以将一个引擎,会做runPipeline过程中为您服务。 这是类似的生成器/导演模式。 在这个过程中的步骤将如下:

  1. 获取输入
  2. 使用工厂方法来获得正确的接口(英文/中国)
  3. 通过接口转换成你的引擎
  4. runPipeline并获得结果

extends VS implements的话题,阿伦赫鲁伯去有点洁癖解释偏爱Interfaces



后续行动您的评论:

我在这里Builder模式的应用程序的解释是,你有一个Factory ,将返回PipelineBuilderPipelineBuilder在我的设计是一个encompases A,B,C,但你可以为每个单独的建设者,如果你喜欢。 此构建则是给你的PipelineEngine它使用Builder生成的结果。

由于这使得使用工厂提供建设者,你的想法上面的工厂仍然在机智,充满了它的缓存机制。

至于您所选择的abstract扩展,你必须给予你的选择PipelineEngine重物的所有权。 但是,如果你去abstract的方式,请注意,您所声明的共享字段是private ,因此不会提供给你的子类。

我喜欢的基本设计。 如果类是很简单的,我可能会考虑巩固A / B / C的工厂为一个类,因为它似乎有可能是行为在这一水平有些共享。 我假设这些都是真的比他们似乎更复杂,但是,这就是为什么这是不可取的。

使用工厂以减少元件之间的耦合的基本做法是合理的,海事组织。

如果我没有记错,你叫什么工厂实际上是依赖注入的一个很好的形式。 你是选择一个对象实例,它是最能满足你参数的需要,并返回。

如果我是对的,你可能想看看DI平台。 他们这样做,你做了什么(这是非常简单的,对吧?),那么他们增加一些更多的能力,你可能现在不需要,但您可能会发现将有助于你以后。

我只是建议你看看现在的问题都解决了。 DI是那么容易做到的自己,你几乎不需要任何其他工具,但他们可能已经发现了,你还没有考虑的情况。 谷歌发现了蝙蝠很多非常好看的环节。

从我所看到的DI,很可能你会想你的“管道”的整个创作搬进了工厂,使之完成这样的链接给你,只是交给你什么,你需要解决一个具体的问题,但我现在真的达到了 - 我的DI的专业知识,只是比我的代码的知识更好一点(换句话说,我最拉这我的屁股)。

分类:java的 时间:2015-03-15 人气:0
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.613 (s). 10 q(s)