Вы действительно не нужен шаблон еще. Просто выполните сервис чистым способом, так что где-то есть метод 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);
Научиться считать - один, два, много. Когда вы нажмете многих, подумайте о рефакторинге к шаблону. Возможно, вам не удалось реализовать более двух сервисов, поскольку вы работаете над каркасом для них, вместо того, чтобы делать что-то полезное.
Если вы сделать есть потребность в более динамичных услуг, а также может выбрать на основе только домен верхнего уровня, то я бы, наверное, есть карта - это 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
ли самое простое первое, второе, самое простое, что второе и самое сложное, если вы должны.
+1 Согласен. Желаю, чтобы у меня было более 1 upvote ... –