你还不需要一个模式。只需以干净的方式实现服务,以便在某处有一个Image FlikrApi.GetImage(Url) 方法。
// client code
Image image = flickApi.GetImage(url);
当您来实现您的第二个服务时,您将有一些要求,即如何根据 Url 决定调用哪个函数。然后,您可以决定如何操作 - 对于两个服务,它可能就像切换顶级域名一样简单。所以你有一个开关,它在一个或另一个对象上调用一个或另一个方法。
readonly FlickrApi flikrApi = new FlickrApi();
readonly WhateverApi whateverApi = new WhateverApi(); // third party
Image GetImage (Url uri) {
switch (url.TopLevelDomain()) {
case "flickr.com":
return flikrApi.GetImage(url);
break;
case "whatever.com":
return whateverApi.GetWhateverImage(url);
break;
default:
throw new UnhandledUriException(uri);
}
// client code
Image image = GetImage(uri);
学会数数 - 一、二、多。当您遇到许多问题时,请考虑重构为一种模式。可能您无法实现两个以上的服务,因为您正在为它们开发一个框架,而不是做一些有用的事情。
如果您确实需要更多动态服务,并且只能基于顶级域进行选择,那么我可能会有一个地图 - 一个填充有 tlds 的 Dictionary<string, Func<Url,Image>>和服务代表。
readonly Dictionary<string, Func<Url,Image>> apis = new ...;
ImageApi () {
apis["flickr.com"] = new FlickrApi().GetImage;
apis["whatever.com"] = new WhateverApi().GetWhateverImage;
apis["zzze.com"] = (uri) => Zoobers.GetWhateverImage(new ZooberCreds(), uri.ToString());
}
static Image GetImage (Url uri) {
string tld = urli.TopLevelDomain();
if (!imageApis.ContainsKey(tld)) throw new UnhandledUriException(uri);
return imageApis[tld](uri);
}
// client code unchanged
在没有闭包/委托的语言中,您可以定义一个接口并使用它们,但是 C# 比这更好,并且使用内置函数类型可以让您使用任何合适的函数,而不必创建一个类只是为了符合接口。这不完全是策略模式,因为上下文和策略之间没有结构关系——在策略模式中,有一个上下文有一个策略,只有一个策略,并且该策略可以改变。在这里,我们根据一个简单的条件在策略之间进行选择。
如果您对决定使用哪个服务有更复杂的要求,那么您最终可能会遍历IImageApi 的接口列表,其中接口包含一个bool HandlesUrl(Url) 方法来询问服务是否识别Url .在这种情况下,您必须使用包装器,而不是使用委托来与任何第三方代码对话。
interface IImageApi {
bool HandlesUri(Url);
Image GetImage(Url);
}
readonly List<IImageApi> apis = new ...;
ImageApi () {
apis.Add(new FlickrApi()); // you wrote this, so it can implement the interface
apis.Add(new WhateverApiAdapter()); // third party requires adapter
apis.Add(new ZoobersApiAdapter()); // ditto
// or you can use something like MEF to populate the list
}
static Image GetImage (Url uri) {
foreach (var api in apis)
if (api.HandlesUri(uri))
return api.GetImage(uri);
throw new UnhandledUriException(uri);
}
// client code unchanged
首先做最简单的事情,其次做最简单的事情,如果必须的话,做最复杂的事情。