Недостаток использования абстрактной фабрики и того, какой шаблон к ней относится
В интервью я столкнулся со следующим вопросом, для которого я не смог найти никакого решения в Google или переполнения стека. Я не знаю, действительно ли это правильный вопрос (поскольку мне не дали никакого контекста. В каком контексте он говорил)??
Меня попросили рассказать, что является хорошо известной проблемой с шаблоном Abstract Factory и какие шаблоны решают эту проблему.
Так что кто-нибудь может помочь мне выяснить, в чем именно заключается эта проблема (Секрет)
Каковы недостатки абстрактного шаблона фабричного дизайна?
Я перешел по этой ссылке, но не смог выяснить, какие другие недостатки шаблона связаны с абстрактной фабрикой.
3 ответа
Цитата из "Шаблонов проектирования" от GoF (вид Библии для программистов): "Поддерживать новые виды продуктов сложно. Расширить абстрактные фабрики для производства новых видов продуктов непросто. Это связано с тем, что интерфейс AbstractFactory исправляет набор продуктов, которые могут Создание новых видов продуктов требует расширения интерфейса фабрики, что включает изменение класса AbstractFactory и всех его подклассов.
Взгляните на статью по созданию источников на Abstract Factory.
Иногда творческие модели являются конкурентами: бывают случаи, когда Prototype
или же Abstract Factory
может быть использовано с пользой. В другое время они дополняют друг друга.
Часто проекты начинаются с использования Factory Method
(менее сложный, более настраиваемый, подклассы разрастаются) и развиваться в направлении Abstract Factory
, Prototype
, или же Builder
(более гибкий, более сложный), когда дизайнер обнаруживает, где требуется большая гибкость.
Для строительства сложного объекта, Builder
это правильный выбор, который обеспечивает большую гибкость. Может быть, ваш интервьюер ищет такой ответ.
Как говорит @o_weisman; основным недостатком AF является расширяемость, но если есть метод, позволяющий решить эту проблему, с точки зрения дизайна (общее многоразовое решение часто встречающейся проблемы), он будет частью AF по умолчанию. Поэтому я думаю, что этот вопрос без контекста не является действительным вопросом.
Один из способов избежать изменения интерфейса и, таким образом, сломать клиент, - использовать только один метод Create для создания всех элементов. Но я сомневаюсь, что это шаблон с официальным названием.
то есть на C#:
namespace ConsoleApplication1
{
public enum Appearance
{
Win,
OSX
}
interface IButton
{
void Paint();
}
interface ITextBox
{
void Paint();
}
interface IGUIFactory
{
TElement CreateGUIElement<TElement>() where TElement : class;
}
class GUIFactory
{
public static IGUIFactory Create(Appearance lookAndFeel) {
if (lookAndFeel == Appearance.Win) { return new WinFactory(); }
if (lookAndFeel == Appearance.OSX) { return new OSXFactory(); }
throw new NotImplementedException();
}
}
abstract class AGUIFactory : IGUIFactory
{
public TElement CreateGUIElement<TElement>() where TElement : class
{
if (typeof(IButton) == typeof(TElement)) { return CreateButton() as TElement; }
if (typeof(ITextBox) == typeof(TElement)) { return CreateTextBox() as TElement; }
throw new NotImplementedException();
}
protected abstract IButton CreateButton();
protected abstract ITextBox CreateTextBox();
}
class WinFactory : AGUIFactory
{
protected override IButton CreateButton()
{
return new WinButton();
}
protected override ITextBox CreateTextBox()
{
return new WinTextBox();
}
}
class OSXFactory : AGUIFactory
{
protected override IButton CreateButton()
{
return new OSXButton();
}
protected override ITextBox CreateTextBox()
{
return new OSXTextBox();
}
}
class WinButton : IButton
{
public void Paint()
{
Console.WriteLine("Windown button paint");
}
}
class OSXButton : IButton
{
public void Paint()
{
Console.WriteLine("OSX button paint");
}
}
class WinTextBox : ITextBox
{
public void Paint()
{
Console.WriteLine("Windown TextBox paint");
}
}
class OSXTextBox : ITextBox
{
public void Paint()
{
Console.WriteLine("OSX TextBox paint");
}
}
class Program
{
static void Main()
{
IGUIFactory factory;
IButton btn;
ITextBox txb;
factory = GUIFactory.Create(Appearance.Win); //UserSettings.LookAndFeel
btn = factory.CreateGUIElement<IButton>();
txb = factory.CreateGUIElement<ITextBox>();
btn.Paint();
txb.Paint();
factory = GUIFactory.Create(Appearance.OSX);
btn = factory.CreateGUIElement<IButton>();
txb = factory.CreateGUIElement<ITextBox>();
btn.Paint();
txb.Paint();
Console.ReadLine();
}
}
}