Зрозумійте відмінності в мотиваціях:
Припустимо, ви будуєте інструмент, у якому є об'єкти та конкретна реалізація взаємозв'язків об'єктів. Оскільки ви передбачаєте зміни в об'єктах, ви створили непрямий характер, поклавши відповідальність за створення варіантів об'єктів іншому об'єкту ( ми називаємо це абстрактним заводом ). Ця абстракція знаходить користь, оскільки ви передбачаєте майбутні розширення, що потребують варіантів цих об'єктів.
Ще одна досить інтригуюча мотивація в цій лінії думок - це випадок, коли кожен або будь-який з об'єктів з усієї групи матиме відповідний варіант. Виходячи з деяких умов, буде використовуватися будь-який з варіантів, і в кожному випадку всі об'єкти повинні бути одного варіанту. Це може бути трохи протилежним інтуїтивно зрозумілим, оскільки ми часто схиляємось до того, що, якщо варіанти об'єкта дотримуються загального єдиного контракту ( інтерфейс у більш широкому сенсі ), конкретний код реалізації ніколи не повинен порушуватися. Інтригуючий факт полягає в тому, що не завжди це вірно, особливо коли очікувана поведінка не може бути змодельована контрактом на програмування.
Простий ( запозичення ідеї у GoF ) - це будь-які програми графічного інтерфейсу, наприклад, віртуальний монітор, який імітує зовнішній вигляд MS або Mac або OS OS OS. Наприклад, коли всі об’єкти віджетів, такі як вікно, кнопка тощо, мають варіант MS, за винятком смуги прокрутки, яка походить від варіанту MAC, призначення інструменту не вдається погано.
Ці вищевикладені випадки є основоположною потребою абстрактних заводських моделей .
З іншого боку, уявіть, що ви пишете фреймворк, щоб багато людей могли будувати різні інструменти ( наприклад, той, що наведений вище ), використовуючи ваш фреймворк. За самою ідеєю рамки вам не потрібно, хоч ви і не могли використовувати конкретні об'єкти у своїй логіці. Ви швидше ставите кілька контрактів високого рівня між різними об'єктами та способами їх взаємодії. Хоча ви ( як розробник фреймворку ) залишаєтесь на дуже абстрактному рівні, кожен розробник цього інструменту змушений слідувати вашим структурам фреймворку. Однак вони ( конструктори інструментів ) мають свободу вирішувати, який об’єкт будувати та як взаємодіють усі створені ними об’єкти. На відміну від попереднього випадку ( абстрактного заводського зразка ), ви ( як творець рамки)) не потрібно в цьому випадку працювати з конкретними предметами; і, скоріше, може залишатися на рівні договору об'єктів. Крім того, на відміну від другої частини попередніх мотивацій, у вас або у виробників інструментів ніколи не виникає ситуацій змішування об'єктів із варіантами. Тут, поки рамковий код залишається на рівні договору, кожен виробник інструментів обмежується ( за характером самого випадку ) використанням власних об'єктів. Створення об'єктів у цьому випадку делегується кожному виконавцеві, а постачальники фреймворків просто забезпечують єдині методи створення та повернення об'єктів. Такі методи неминучі для розробника фреймворку, щоб перейти до свого коду і має спеціальну назву, що називається Фабричний метод ( Factory Method Pattern для базового шаблону ).
Кілька приміток:
- Якщо ви знайомі з "методом шаблонів", то ви побачите, що заводські методи часто використовуються з шаблонових методів у разі програм, що стосуються будь-якої форми фреймворку. На відміну від цього, шаблонні методи прикладних програм часто є простою реалізацією певного алгоритму та недійсними фабричними методами.
- Крім того, для повноти думок, використовуючи рамки ( згадані вище ), коли виробник інструментів будує інструмент, всередині кожного фабричного методу, замість створення конкретного об'єкта, він / вона може додатково делегувати відповідальність абстрактному -фабрикальний об'єкт за умови, що інструмент-конструктор передбачив варіації конкретних об'єктів для майбутніх розширень.
Приклад коду:
//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method
startGame(){ //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}
//Part of Tool-builder code
Ludo inherits BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}
//Part of Tool-builder code
Chess inherits BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}