Полностью осознаю, что это очередной вопрос из серии "Разница между абстрактным классом и интерфейсом". И должен сказать, что для меня эти две концепции ясны или возможно нет раз задаю этот вопрос :)
Наверное каждый второй, если не первый из девелоперов использует порождающий паттерн "Фабричный метод" и меня интересует вопрос, так какую абстракцию лучше использовать при реализация этого паттерна: абстрактный класс или интерфейс?
Туториалы в сети тоже не едины в этом: кто-то рассказывает этот паттерн при помощи абстрактного класса, а кто-то при помощи интерфесов. Хотя должен заметить, что большинство статей касаемо фабричного метода ведут свои рассуждения на абстрактных классах.
Вот пример из википедии, который рассказывает паттерн на
Абстрактных классах
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++, в котором интерфейсов просто нет.
Комментариев нет:
Отправить комментарий