Страницы

Поиск по вопросам

вторник, 5 марта 2019 г.

Что использовать абстрактный класс или интерфейс в фабричном методе?

Полностью осознаю, что это очередной вопрос из серии "Разница между абстрактным классом и интерфейсом". И должен сказать, что для меня эти две концепции ясны или возможно нет раз задаю этот вопрос :)
Наверное каждый второй, если не первый из девелоперов использует порождающий паттерн "Фабричный метод" и меня интересует вопрос, так какую абстракцию лучше использовать при реализация этого паттерна: абстрактный класс или интерфейс?
Туториалы в сети тоже не едины в этом: кто-то рассказывает этот паттерн при помощи абстрактного класса, а кто-то при помощи интерфесов. Хотя должен заметить, что большинство статей касаемо фабричного метода ведут свои рассуждения на абстрактных классах.
Вот пример из википедии, который рассказывает паттерн на
Абстрактных классах
namespace CSharpConsoleApp { abstract class AbstractProduct { public abstract string GetType(); }
class ConcreteProductA : AbstractProduct { public override string GetType() { return "ConcreteProductA"; } }
class ConcreteProductB : AbstractProduct { public override string GetType() { return "ConcreteProductB"; } }
abstract class AbstractCreator { public abstract AbstractProduct FactoryMethod(); }
class ConcreteCreatorA : AbstractCreator { public override AbstractProduct FactoryMethod() { return new ConcreteProductA(); } }
class ConcreteCreatorB : AbstractCreator { public override AbstractProduct FactoryMethod() { return new ConcreteProductB(); } } class Program { static void Main(string[] args) { AbstractCreator[] creators = { new ConcreteCreatorA(), new ConcreteCreatorB() }; foreach (AbstractCreator creator in creators) { AbstractProduct product = creator.FactoryMethod(); Console.WriteLine("Created {0}", product.GetType()); }
Console.Read(); } } }
а это переделанный мной вариант на
Интерфейсах
namespace CSharpConsoleApp { interface IProduct { string GetType(); }
class ProductA : IProduct { public string GetType() { return "ProductA"; } }
class ProductB : IProduct { public string GetType() { return "ProductB"; } } interface ICreatorProduct { IProduct FactoryMethod(); }
class CreatorProductA : ICreatorProduct { public IProduct FactoryMethod() { return new ProductA(); } }
class CreatorProductB : ICreatorProduct { public IProduct FactoryMethod() { return new ProductB(); } }
class Program { static void Main(string[] args) { ICreatorProduct[] productCreators = { new CreatorProductA(), new CreatorProductB() }; foreach (ICreatorProduct creatorProduct in productCreators) { IProduct product = creatorProduct.FactoryMethod(); Console.WriteLine("Created {0}", product.GetType()); }
Console.Read(); } } }

Так какова лучшая практика использования данного паттерна в плане абстракций?


Ответ

Смысл абстрактного класса — совместное использование кода классами-потомками. Абстрактный класс нужен для того, чтобы было легко создавать немного отличающиеся классы, общую часть которых вы выносите в реализованные методы абстрактного класса.
В вашем случае абстрактный класс не нужен. В вашем коде смысл AbstractProduct состоит лишь в том, чтобы в дочернем классе затребовать наличия метода string GetType(). Точно так же смысл AbstractCreator лишь в том, чтобы в дочернем классе затребовать наличия метода AbstractProduct FactoryMethod(). Это прекрасно ложится на предназначение интерфейсов.
Вывод: интерфейсы в данном коде намного более естественны.

Предположу, что код, который использует абстрактные классы, написан для языка C++, в котором интерфейсов просто нет.

Комментариев нет:

Отправить комментарий