这可能是最容易用代码解释的(这当然不是实际代码,但它具有相同的属性):
我的界面看起来像这样:
public interface ISomeProvider
{
object GetFoo1(); //<-- This needs caching
//These others don't
object GetFoo2();
object GetFoo3();
//And let's say 20 more
}
这有一个像这样的实现:
//NOTE: Sealed class otherwise we could inherit from it
public sealed class SuperCleverProvider : ISomeProvider
{
public object GetFoo1()
{
return "a";
}
public object GetFoo2()
{
return "b";
}
public object GetFoo3()
{
return "b";
}
}
现在其中一个调用,让我们说GetFoo1真的很重,所以我想提供一个新版本的接口,其中使用旧版本的实例缓存对它的调用。
我现在这样做:
public class CachedSuperCleverProvider : ISomeProvider
{
private readonly SuperCleverProvider _provider;
public CachedSuperCleverProvider(SuperCleverProvider provider)
{
_provider = provider;
}
private object UsingCache<T>(string cacheKey, Func<T> eval)
{
//Pretend this does caching. This is not related to the question
throw new NotImplementedException();
}
public object GetFoo1()
{
return UsingCache("foo1", _provider.GetFoo1);
}
//The code below this point is what I want to get rid of
public object GetFoo2()
{
return _provider.GetFoo2();
}
public object GetFoo3()
{
return _provider.GetFoo3();
}
//And so on for all the rest
}
这有两个问题(至少):
有人能想到一种没有这些问题的方法吗?
答案 0 :(得分:3)
三个选项:
我个人可能会选择第三个选项,除非你真的发现自己这么做了。权衡每个选项的成本 - 您实际花费多少时间来添加此委托?
我个人喜欢将这种东西视为一种语言特征 - “除非我覆盖它,否则通过这个字段委托给这个界面”,但显然目前还不存在......
答案 1 :(得分:0)
这是我的建议。它并没有太好,但会简化包装过程。
创建课程SomeProviderWrapper
:
public class SomeProviderWrapper : ISomeProvider
{
protected ISomeProvider WrappedProvider { get; private set; }
protected SomeProviderWrapper(ISomeProvider wrapped)
{
if (wrapped == null)
throw new ArgumentNullException("wrapped");
WrappedProvider = wrapped;
}
public virtual object GetFoo1()
{
return WrappedProvider.GetFoo1();
}
public virtual object GetFoo2()
{
return WrappedProvider.GetFoo2();
}
public virtual object GetFoo3()
{
return WrappedProvider.GetFoo3();
}
}
现在将包装降级为自己的类,您可以编写缓存版本:
public class CachedSuperCleverProvider : SomeProviderWrapper
{
public CachedSuperCleverProvider(ISomeProvider wrapped) : base(wrapped) { }
private object UsingCache<T>(string cacheKey, Func<T> eval)
{
throw new NotImplementedException();
}
public override object GetFoo1()
{
return UsingCache("foo1", WrappedProvider.GetFoo1);
}
}
这使委托代码不会超出您的超级聪明的提供程序。您仍然需要维护委托代码,但它不会污染您的缓存提供程序的设计。