假设我有一个用于翻译文本的简单接口(C#中的示例代码):
public interface ITranslationService
{
string GetTranslation(string key, CultureInfo targetLanguage);
// some other methods...
}这个接口的第一个简单实现已经存在,只需为每个方法调用进入数据库。假设启动时正在翻译UI,则每个控件都会有一个数据库调用。
为了改进这一点,我想添加以下行为:
一收到对一种语言的请求,就从这种语言中获取所有的翻译并缓存它们。所有翻译请求都从缓存中处理。
我考虑将这个新行为作为装饰器来实现,因为由装饰者实现的接口的所有其他方法都将简单地委托给修饰的实例。
但是,GetTranslation的实现根本不会使用修饰实例的GetTranslation来获得特定语言的所有翻译。它将对数据库启动自己的查询。
这破坏了装饰器模式,因为装饰实例提供的所有功能都被跳过。如果有其他装饰师参与,这将成为一个真正的问题。
我的理解是装饰应该是附加的。但是,在这种情况下,装饰器将替换修饰实例的行为。
我真的想不出一个很好的解决办法--你会怎么解决?一切都是允许的,甚至是对ITranslationService本身的完全重新设计。
发布于 2013-06-25 12:38:14
保留ITranslationService,但不要直接针对缓存或数据库实现调用,而是发送到一个对象IRepository,该对象使用首选的IProviders列表,该列表提供了对底层持久性机制的访问。
第一个,或者通常是“首选提供者”,是一个CacheProvider。第二个是您的主LocalDatabaseTranslationProvider。可以想象,可能有第三个或更多的提供者。列表中的最后一个提供程序是最不可取的,但它是可靠的后备提供程序。例如,可以采用第三方翻译服务的形式。它将作为像RemotePartnerTranslationProvider这样的对象代理服务来实现。
每个提供程序都将实现一个公共接口,该接口允许策略不同,因此,无论选择哪个提供程序,无论每个提供程序如何提供读和写,存储库都对每个提供程序进行操作,并以相同的方式从每个提供程序接收。存储处负责在必要时提供供应商之间的协调和冲突解决。
在其他问题中,您也可以查看每个提供程序的可观察接口,因为您需要在存储库中的所有/大多数提供程序之间传播/推送状态/信号,例如在清理/关闭时正确关闭或处理它们。
发布于 2013-06-25 11:40:02
许多可能选项的可行性取决于ITranslationService接口当前实现的关闭程度。
GetTranslation方法。GetTranslation实现更改为使用战略模式,其中一种策略总是进入数据库,而另一种策略使用缓存。https://softwareengineering.stackexchange.com/questions/202670
复制相似问题