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


124

Більшість визначення говорить:

Абстрактна фабрика пропонує інтерфейс для створення сімей пов’язаних об'єктів без конкретизації їх конкретних класів

У чому полягає абстрактний заводський візерунок, оскільки ми можемо досягти поставленого завдання, створивши сам предмет конкретного класу. Чому у нас є заводський метод, який створює об’єкт класу Бетон?

Будь ласка, надайте мені будь-який приклад із реального життя, де я повинен реалізовувати шаблон абстрактного Фактора?

Відповіді:


218

Анотація Фабрика - це дуже центральна модель дизайну для вприскування залежностей (DI). Ось перелік запитань щодо переповнення стека, де застосування рішення Factory Factory було прийнято як рішення.

Наскільки я розумію, ці питання представляють реальні проблеми чи проблеми, які виникли у людей, тож варто почати з деяких прикладів із реального життя:


6
Усі ці приклади описують заводський метод моделей, оскільки всі вони повертають єдиний інтерфейс продукту. Жодне з них не є абстрактним заводським зразком, оскільки жоден з них не створює сімейство відповідних інтерфейсів продуктів.
jaco0646

32
В інтересах повного розголошення автор цієї відповіді повинен був дати зрозуміти, що він також є автором кожної з пов'язаних відповідей; тож цей список НЕ є репрезентативним зразком спільноти SO.
jaco0646

1
@ jaco0646 IIRC, заводський метод - це спеціалізація шаблону методу шаблонів , який спирається на спадкування. Я, можливо, помиляюся, оскільки зараз подорожую, і не маю при собі своєї книги GoF. Що ви маєте на увазі під "жодним із них не створювати родину пов'язаних інтерфейсів продуктів"?
Марк Семанн

1
Найпростіша підказка, яка вказує на те, що фабрика не відповідає абстрактному заводському зразку, - це підрахунок абстрактних продуктів, які виробляє фабрика (я використовував термін "продуктові інтерфейси" замість "абстрактних продуктів", щоб уникнути зайвого використання слова "абстрактний") . Фабрика, яка виробляє єдиний абстрактний продукт, не може бути абстрактною фабрикою, тому що за визначенням, "Абстрактна фабрика" виробляє сімейство супутніх товарів . Важливо зауважити, що ця сім'я стосується не різних реалізацій одного інтерфейсу, а продуктів, що мають різні, пов'язані між собою інтерфейси.
jaco0646

1
Ось приклад oodesign.com/abrief-factory-pattern.html . Для цього спочатку був створений абстрактний заводський зразок.
user2802557

23

Прикладом реального життя для використання абстрактної фабрики є надання доступу до двох різних джерел даних. Припустимо, що ваша програма підтримує різні сховища даних. (наприклад, база даних SQL та файл XML). У вас є два різних інтерфейсу доступу до даних, наприклад, IReadableStoreта IWritableStoreвизначення загальних методів, очікуваних вашою програмою, незалежно від типу використовуваного джерела даних.

Який тип джерела даних використовуватиметься, не повинен змінювати спосіб отримання клієнтським кодом класів доступу до даних. Ви AbstractDataAccessFactoryзнаєте, який тип джерела даних налаштований і забезпечує конкретну Фабрику для клієнтського коду, тобто SqlDataAccessFactoryабо XmlDataAccessFactory. Ці бетонні заводи можуть створювати конкретні реалізації, наприклад, SqlReadableStoreта SqlWriteableStore.

DbProviderFactory в .NET Framework є прикладом цього шаблону.


18
Ця відповідь могла би точно описати шаблон заводського методу або статичний заводський візерунок, але не абстрактний заводський шаблон.
jaco0646

5

Якщо я правильно вас розумію - питання полягає в тому, чому ми маємо і Фабричний метод, і абстрактні заводські зразки. Вам потрібна абстрактна фабрика, коли різні поліморфні класи мають різні процедури інстанції. І ви хочете, щоб якийсь модуль створював екземпляри та використовував їх, не знаючи жодних деталей ініціалізації об'єкта. Наприклад - ви хочете створити об'єкти Java, роблячи деякі обчислення. Але деякі з них є частиною програми, а інші байт-коди повинні читатися з БД. З іншого боку - навіщо нам потрібен заводський метод? Погодьтеся, ця абстрактна фабрика перекриває її. Але в деяких випадках - набагато менше коду писати, менша кількість класів та інтерфейсів полегшує розуміння системи.


4

У чому полягає абстрактний заводський візерунок, оскільки ми можемо досягти поставленого завдання, створивши сам предмет конкретного класу. Чому у нас є заводський метод, який створює об’єкт класу Бетон?

За відсутності « Фабрики абстрактних» , Клієнт повинен знати деталі конкретних класів. Ця герметична муфта була вилучена з " Фабрика абстрактних" .

Тепер Factory Method виставляє контракт, який повинен використовувати клієнт. Ви можете додати більше продуктів на свою фабрику, додавши нові продукти, що реалізують інтерфейс, що піддається фабричному методу.

Для кращого розуміння зверніться до цих пов’язаних питань ДП:

У чому полягає основна відмінність між фабричними та абстрактними фабричними візерунками?

Намір:

Забезпечте інтерфейс для створення сімей пов’язаних або залежних об'єктів, не вказуючи їх конкретні класи.

Ви можете зрозуміти , Intent, структура, Перелік і Емпіричні правила в Abstract Factory шаблон з цієї sourcemaking статті.

Контрольний список:

  1. Вирішіть, чи незалежність платформи та створення послуг є поточним джерелом болю.
  2. Намалюйте матрицю платформ у порівнянні з продуктами .
  3. Визначте заводський інтерфейс, який складається з фабричного методу для кожного продукту.
  4. Визначте заводський похідний клас для кожної платформи, який інкапсулює всі посилання на нового оператора.
  5. Клієнт повинен піти у відставку всіх посилань на новий, і використовувати фабричні методи для створення продукту об'єктів.

2

Абстрактні заводи чудово підходять для підтримки декількох платформ, зберігаючи базу коду уніфікованою. Припустимо, у вас є велика програма Qt або GTK + або .NET / Mono, яку потрібно запустити в Windows, Linux та OSX. Але у вас є функція, яка реалізується по-різному на кожній платформі (можливо, через API kernel32 або функцію POSIX).

public abstract class Feature
{
    public abstract int PlatformSpecificValue { get; }

    public static Feature PlatformFeature
    {
        get
        {
            string platform;
            // do platform detection here
            if (platform == "Win32")
                return new Win32Feature();
            if (platform == "POSIX")
                return new POSIXFeature();
        }
    }

    // platform overrides omitted
}

Завдяки цій абстрактній фабриці ваш інтерфейс не повинен нічого знати про поточну платформу.

Feature feature = Feature.PlatformFeature;
Console.WriteLine(feature.PlatformSpecificValue);

1
Я не розумію, чим це відрізняється від використання фабричних методів для повернення абстрактного типу, щоб клієнт не знав деталей реалізації?
kiwicomb123

1

Якщо поглянути на дизайнерські шаблони, майже всі вони можуть бути зайвими. Але яка закономірність означає загальноприйнятий підхід для вирішення подібного типу проблем. Шаблон дизайну надає вам підхід на рівні дизайну або рішення набору подібних типів дизайнерської проблеми. Використання схеми дизайну допоможе вам вирішити свою проблему і, отже, швидше поставити її.


1

легко, уявляючи, що у вас є код, який працює з абстракцією, ви повинні створювати абстракції, а не конкретні класи.

Ви завжди повинні працювати проти абстракцій, оскільки зможете краще змінити код.

Це хороший приклад: http://en.wikipedia.org/wiki/Abrief_factory_pattern#C.23


1

Я вважаю абстрактний заводський візерунок завищеним.

Перш за все, це не відбудеться , що часто , що у вас є набір взаємозв'язаних типів , які ви хочете створити екземпляр.

По-друге, рівень опосередкованості (абстрагування), що забезпечується інтерфейсами, зазвичай достатній при роботі з введенням залежності.

Типовий приклад WindowsGui vs MacGui vs…, де у вас є WindowsButton, MacButton, WindowsScrollBar, MacScrollbar тощо, часто легше реалізувати, визначаючи конкретні кнопки, смуги прокрутки тощо, використовуючи шаблон відвідувача та / або інтерпретатора для надання шаблону. фактична поведінка.


для цього є конкретна мета. за допомогою ін'єкції залежності ви не хочете, щоб локатори сервісу подалі від композитного кореня. замість цього ви використовуєте введений абстрактний завод.
Адам Туліпер - MSFT

2
ну ... використання локатора сервісу з DI - це анти-патетен. Абстрактна фабрика - це універсальне рішення, коли нам потрібно створити ЗАВАНТАЖЕННЯ із значень часу виконання.
TheMentor

1

Я думаю, що в місцях, де ваші інстанції дуже складні, занадто складні та потворні для однієї фабрики і занадто складні, щоб інтерфейс інтерфейсу зрозумів, є місце для абстрактного фабричного візерунка.

Скажімо, це бренд TYPE_A - це не один клас. Скажімо, є сім'я з 100 видів подібних класів Type-A, і вам потрібно інстанціювати один об’єкт з них. Уявіть, що є детальна складна інформація, необхідна для того, щоб зробити правильний об'єкт з бренда багатьох подібних типів об'єктів, і в цьому об'єкті об'єкта потрібно точно знати, які параметри налаштовувати і як їх налаштовувати.

На спеціальній фабриці для цієї марки ми будемо їх розрізняти і отримувати точний об'єкт для інстанції, а також як інстанціювати його. ми будемо знати, що відповідно до входу з мережі (скажімо, який колір доступний в інтернет-магазині), а також з інших програм та служб, що працюють у фоновому режимі (параметри користувальницькому інтерфейсу про них не відомі).

І, можливо, завтра у нас з’явиться інша сім'я, скажімо, тип_B та type_C для інстанції. Таким чином, у інтерфейсу користувача буде "якщо ще" знати, чи бажає користувач "type_A", "type_B" або "type_C" - але класи фабрик вирішать, який саме клас із типу (від родини) будувати, і як його настроїти - які значення встановити для його параметрів, або надіслати його контрагенту. Все це - за багатьма параметрами, про які користувальницький інтерфейс не усвідомлює. Все це буде занадто багато для одного фабричного класу.


1

Приклад реального життя наведено в просторі імен System.Data.Common, який має абстрактні базові класи, які включають DbConnection, DbCommand і DbDataAdapter і якими надаються постачальники даних .NET Framework, такі як System.Data.SqlClient та System.Data.OracleClient, які дозволити розробнику писати загальний код доступу до даних, який не залежить від конкретного постачальника даних.

Клас DbProviderFactories надає статичні методи створення екземпляра DbProviderFactory. Потім екземпляр повертає правильний сильно набраний об’єкт на основі інформації про постачальника та рядка з'єднання, що постачається під час виконання.

Приклад:

 DataTable allProvidersTable = DbProviderFactories.GetFactoryClasses();

введіть тут опис зображення

        /* Getting SqlClient family members */
        DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");
        DbCommand dbCommand = dbProviderFactory.CreateCommand();
        DbConnection dbConnection = dbProviderFactory.CreateConnection();
        DbDataAdapter dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        SqlClientFactory sqlClientFactory = (SqlClientFactory)dbProviderFactory;
        SqlConnection sqlConnection = (SqlConnection)dbConnection;
        SqlCommand sqlCommand = (SqlCommand) dbCommand;
        SqlDataAdapter sqlDataAdapter = (SqlDataAdapter) dbDataAdapter;

        /* Getting OracleClient family members*/
        dbProviderFactory = DbProviderFactories.GetFactory("System.Data.OracleClient");
        dbCommand = dbProviderFactory.CreateCommand();
        dbConnection = dbProviderFactory.CreateConnection();
        dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        OracleClientFactory oracleClientFactory = (OracleClientFactory)dbProviderFactory;
        OracleConnection oracleConnection = (OracleConnection)dbConnection;
        OracleCommand oracleCommand = (OracleCommand)dbCommand;
        OracleDataAdapter oracleDataAdapter = (OracleDataAdapter)dbDataAdapter;

Приклад-2 введіть тут опис зображення

Архітектура кодового рішення введіть тут опис зображення

Екземпляри конкретних заводів надаються за допомогою статичного фабричного методу, як показано нижче

public  class FurnitureProviderFactory
{
    public static IFurnitureFactory GetFactory(string furnitureType)
    {
        if (furnitureType == "Wood")
        {
            return new WoodenFurnitureFactory();
        }
        if (furnitureType == "Plastic")
        {
            return new PlasticFurnitureFactory();
        }
        throw new Exception("Undefined Furniture");
    }
}

0

Щоб відповісти безпосередньо на ваше запитання, ви, ймовірно, можете піти без використання такої схеми дизайну.

Однак майте на увазі, що більшість проектів у реальному світі розвиваються, і ви хочете надати певну розширюваність, щоб зробити ваш проект перспективними.

З мого власного досвіду, більшість часу реалізується Фабрика, і в міру зростання проекту він змінюється на більш складні моделі дизайну, такі як абстрактна фабрика.


0

Вся справа в залежності. Якщо вам не байдуже тісне з’єднання та залежності, то вам не потрібна абстрактна фабрика. Але це матиме значення, як тільки ви напишете заявку, яка потребує обслуговування.


0

Скажімо, ви створюєте a.jar, а хтось інший використовує вашу банку і хоче використовувати новий конкретний об'єкт у вашому коді. Якщо ви не використовуєте абстрактну фабрику, вона повинна змінити ваш код або перезаписати ваш код. Але якщо ви використовуєте абстрактну фабрику, то вона може надати фабрику і перейти до вашого коду, і все в порядку.

Вдосконалена версія: Розгляньте нижченаведений сценарій: Хтось ще написав рамки. Рамка використовує абстрактні фабрики та деякі конкретні заводи для створення багатьох об'єктів під час роботи. Таким чином, ви можете легко зареєструвати власну фабрику до існуючих рамок і створити власні об’єкти. Рамка закрита для модифікацій і все ще легко розширюється через абстрактний заводський зразок.


0

Цей шаблон особливо корисний, коли клієнт не знає, який саме тип створити. Для прикладу, скажімо, в шоурумі, що продає виключно мобільні телефони, є запит на смартфони, зроблені Samsung. Тут ми не знаємо точного типу об’єкта, який потрібно створити (якщо припустити, що вся інформація для телефону загорнута у вигляді конкретного об'єкта). Але ми знаємо, що ми шукаємо смартфони, які виробляє Samsung. Ця інформація може бути фактично використана, якщо в нашій конструкції є абстрактна фабрична реалізація.

Розуміння та реалізація абстрактних заводських моделей у C #

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.