Тебе пока не нужен шаблон.Просто внедрите сервис в чистом виде, чтобы где-нибудь был метод 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>>
, заполненная tlds и делегатами сервиса.
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
Сначала сделайте самое простое, затем самое второе, самое простое, второе и наиболеесложная вещь, если вам нужно.