Як відрізняються шаблони проксі, декоратора, адаптера та моста?


403

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


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

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

Відповіді:


648

Проксі, декоратор, адаптер та міст - це всі варіанти "обгортання" класу. Але їх використання різне.

  • Проксі-сервер можна використовувати, коли ви хочете ліниво встановити об'єкт або приховати той факт, що ви викликаєте віддалену службу або контролюєте доступ до об'єкта.

  • Декоратор також називається "Smart Proxy". Це використовується, коли ви хочете додати функціональність об'єкту, але не шляхом розширення його типу. Це дозволяє зробити це під час виконання.

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

  • Bridge дуже схожий на Adapter, але ми називаємо його Bridge, коли ви визначаєте як абстрактний інтерфейс, так і базову реалізацію. Тобто ви не пристосовуєтесь до якогось застарілого чи стороннього коду, ви є дизайнером всього коду, але вам потрібно мати можливість замінювати різні реалізації.

  • Фасад - це інтерфейс вищого рівня (читай: простіший) для підсистеми одного або декількох класів. Припустимо, у вас є складна концепція, для якої потрібно представити кілька об'єктів. Внесення змін до цього набору об’єктів заплутано, оскільки ви не завжди знаєте, який об’єкт має метод, який потрібно викликати. Настав час написати Фасад, який надає методи високого рівня для всіх складних операцій, які Ви можете зробити для колекції об’єктів. Приклад: Модель предметної області для шкільної секції, з допомогою методів , таких як countStudents(), reportAttendance(), assignSubstituteTeacher(), і так далі.


7
Хороша відповідь. Може варто додати кілька прикладів того, де ви бачите це в дикій природі? наприклад, проксі-класи в веб-службах. +1 від мене.
Роб Купер

5
@Rob: дякую, але я вважаю за краще, щоб ця відповідь була короткою та солодкою. Я закликаю вас написати ще одну відповідь із прикладами в дикій природі!
Білл Карвін

8
@RobertDailey Decorator також добре уникати ієрархій типу контролю. Наприклад , скажіть, що у вас є вікно в графічному інтерфейсі, і ви хочете мати додаткові смуги прокрутки. У вас можуть бути класи Window, VScrollWindow, HScrollWindow та VHScrollWindow, або ви можете зробити декоратори VScroll та HScroll у вікні.
Єва

1
@RobertDailey, декоратор - композиція.
Білл Карвін

1
А що робити, якщо ви хочете дублювати інтерфейс загорнутого об’єкта 1: 1, але потім додати кілька додаткових методів? Це декоратор чи перехідник?
donquixote

198

Як йдеться у відповіді Білла, випадки їх використання різні .

Так само їх структури.

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

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

  • Міст і адаптер вказують на існуючий тип. Але міст буде вказувати на абстрактний тип, і адаптер може вказувати на конкретний тип. Міст дозволить вам з’єднати реалізацію під час виконання, тоді як адаптер зазвичай цього не робить.


30
Ваша відповідь у поєднанні з Біллом дуже добре висвітлює 5 розділів «Шаблони дизайну». Можна було б назвати їх більш високим рівнем (читати: простіше) інтерфейсом книги.
Йонас Ейхер

54

Моє взяти на цю тему.

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

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

Перехідник

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

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

Адаптери захищають одну команду від непостійного коду від інших команд; інструмент порятунку життя при роботі з офшорними командами ;-)

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

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

Код мудрий, адаптер "тонкий". Він не повинен додавати багато коду до адаптованого класу, окрім того, щоб просто викликати метод адаптованих та періодичні перетворення даних, необхідні для здійснення таких дзвінків.

У JDK або базових бібліотеках не так багато хороших прикладів адаптера. Розробники додатків створюють Адаптери, щоб адаптувати бібліотеки до інтерфейсів додатків.

Декоратор

Декоратор не тільки делегує, не тільки відображає один метод на інший, вони роблять більше, вони змінюють поведінку деяких предметних методів, він може вирішити взагалі не викликати предметний метод, делегувати інший об’єкт, об’єкт-помічник.

Декоратори, як правило, додають (прозоро) функціональність до загорнутого об'єкта, наприклад, реєстрація, шифрування, форматування або стиснення предмета. Цей новий функціонал може принести багато нового коду. Отже, декоратори, як правило, набагато «товстіші», ніж перехідники.

Декоратор повинен бути підкласом інтерфейсу теми. Їх можна використовувати прозоро замість предметів. Дивіться BufferedOutputStream, він все ще є OutputStream і може бути використаний як такий. Це основна технічна відмінність від адаптерів.

Приклади текстових книг для цілої родини декораторів легко розміщені в JDK - Java IO. Усі класи, такі як BufferedOutputStream , FilterOutputStream та ObjectOutputStream, є декораторами OutputStream . Вони можуть бути шарувати цибулею, де один декоратор знову прикрашається, додаючи більше функціональності.

Проксі

Проксі - не типова обгортка. Об'єднаний об’єкт, тема проксі, може ще не існувати під час створення проксі. Проксі часто створює його всередині. Це може бути важкий об’єкт, створений на вимогу, або це віддалений об'єкт у різних JVM або різних мережевих вузлах і навіть не-Java-об'єкт, компонент у рідному коді. Це зовсім не обов'язково обгортати або делегувати інший об’єкт.

Найбільш типові приклади - віддалені проксі, ініціалізатори важких об'єктів та проксі-сервери доступу.

  • Віддалений проксі - предмет знаходиться на віддаленому сервері, іншому JVM або навіть не в системі Java. Проксі переводить виклики методу на дзвінки RMI / REST / SOAP або все необхідне, захищаючи клієнта від впливу базової технології.

  • Lazy Load Proxy - повністю ініціалізувати об'єкт лише першого або першого інтенсивного використання.

  • Access Proxy - контроль доступу до предмета.

Фасад

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

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

Міст

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

Відмінності конструкторів

Відмінності шаблонів також очевидні при погляді на їх конструктори.

  • Проксі не обертає існуючий об'єкт. У конструкторі немає предмета.

  • Decorator and Adapter обертає вже наявний об'єкт, і такий, як правило,
    надається в конструкторі.

  • Конструктор фасаду бере корінний елемент цілого графіка об'єкта, інакше він виглядає так само, як Адаптер.

Приклад із реального життя - адаптер маршалінгу JAXB . Призначення цього адаптера - це зіставлення простого плоского класу на більш складну структуру, необхідну зовні, і запобігання "забрудненню" предметного класу надмірними анотаціями.


30

У багатьох моделях Міністерства фінансів існує велике перекриття. Всі вони побудовані на силі поліморфізму, а іноді лише по-справжньому відрізняються між собою. (стратегія проти держави)

Моє розуміння шаблонів збільшилось у 100 разів, прочитавши шаблони дизайну Head First Design .

Дуже рекомендую!


9

Усі хороші відповіді експертів уже пояснили, що означає кожен шаблон.

Я прикрашу ключові моменти.

Декоратор:

  1. Додайте поведінку до об'єкта під час виконання . Спадщина - це ключ до досягнення цієї функціональності, що є як перевагою, так і недоліком цієї моделі.
  2. Це змінює поведінку інтерфейсу.

наприклад (з ланцюжком): java.ioкласи пакунків, пов'язані з InputStream& OutputStreamінтерфейсами

FileOutputStream fos1 = new FileOutputStream("data1.txt");  
ObjectOutputStream out1 = new ObjectOutputStream(fos1);

Проксі:

  1. Використовуйте його для лінивої ініціалізації, покращення продуктивності, кешуючи об’єкт і контролюючи доступ до клієнта / абонента . Він може надавати альтернативну поведінку або викликати реальний об'єкт. Під час цього процесу він може створити новий Об'єкт.
  2. На відміну від Decorator , який дозволяє прикувати об'єкти, Proxy не дозволяє ланцюжок.

наприклад: java.rmiпакунки класів.

Адаптер:

  1. Це дозволяє двом непов'язаним інтерфейсам працювати разом через різні об'єкти , можливо, граючи однакову роль.
  2. Це змінює оригінальний інтерфейс .

наприклад java.io.InputStreamReader( InputStreamповертає a Reader)

Міст:

  1. Це дозволяє як абстракціям, так і реалізаціям змінюватися незалежно .
  2. Він використовує склад над успадкуванням .

наприклад, колекційні класи в java.util. Listреалізований ArrayList.

Основні нотатки:

  1. Адаптер забезпечує інший інтерфейс для свого предмета. Проксі надає той же інтерфейс. Decorator забезпечує розширений інтерфейс.
  2. Адаптер змінює інтерфейс об'єкта, Декоратор посилює обов'язки об'єкта.
  3. Декоратор та проксі мають різні цілі, але схожі структури
  4. Адаптер примушує роботу працювати після їх розробки; Міст змушує їх працювати до того, як вони є.
  5. Міст розроблений вперед, щоб абстракція та реалізація змінювалися незалежно. Адаптер оснащений для того, щоб зв'язати взаємозв’язані класи разом
  6. Оформлювач призначений для додання обов'язків перед об'єктами без підкласифікації.

Перегляньте чудові питання / статті SE щодо прикладів різних моделей дизайну

Коли використовувати візерунок декоратора?

Коли ви використовуєте шаблон моста? Чим вона відрізняється від моделі адаптера?

Відмінності між проксі і декоративними малюнками


8

Вони досить схожі, а лінії між ними досить сірі. Я пропоную вам прочитати записи проксі-візерунка та шаблону декораторів у вікі c2.

Записи та дискусії там досить великі, і вони також посилаються на інші відповідні статті. До речі, вікі c2 є чудовим, коли дивуєшся нюансам між різними візерунками.

Підводячи підсумки записів на c2, я б сказав, що декоратор додає / змінює поведінку, але проксі має більше спільного з контролем доступу (лінивий екземпляр, віддалений доступ, безпека тощо). Але, як я вже сказав, лінії між ними сірі, і я бачу посилання на проксі, які легко можна розглядати як декораторів і навпаки.


4

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

  • Проксі інкапсулює доступ зовнішнього та внутрішнього.
  • Декоратор модифікує або розширює поведінку внутрішнього з зовнішнім.
  • Адаптер перетворює інтерфейс із внутрішнього на зовнішній.
  • Міст відокремлює незмінну частину поведінки (зовнішню) від змінної або залежно від платформи частини (внутрішню).

І за варіацією інтерфейсу між внутрішніми та зовнішніми об'єктами:

  • в проксі- інтерфейсах однакові.
  • в Decorator інтерфейси однакові.
  • в адаптері інтерфейси відрізняються формально, але виконують ту ж мету.
  • в Bridge інтерфейси різні концептуально.

4

Це цитата з головних шаблонів дизайну

Визначення належить книзі. Приклади належать мені.

Decorator - не змінює інтерфейс, але додає відповідальності. Припустимо, у вас є автомобільний інтерфейс, коли ви реалізуєте це для іншої моделі автомобіля (s, sv, sl), можливо, вам доведеться додати більше відповідальності за деякі моделі. Як і люк, подушка безпеки тощо.

Адаптер - перетворює один інтерфейс в інший. У вас є автомобільний інтерфейс, і ви хотіли б, щоб він діяв як джип. Тож ви берете машину, модифікуєте її і перетворюєте на джип. Оскільки це не справжній джип. Але діє як джип.

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

По-перше: "Фасад не тільки спрощує інтерфейс, він від'єднує клієнта від підсистеми компонентів. Фасади та адаптери можуть охоплювати кілька класів, але мета фасаду - спростити, а адаптер - перетворити інтерфейс на щось інше. "


1

Я використовую його досить часто під час споживання веб-сервісів. Можливо, проксі-шаблон повинен бути перейменований на щось більш прагматичне, наприклад, "Wrapper Pattern". У мене також є бібліотека, яка є проксі для MS Excel. Це дозволяє дуже легко автоматизувати Excel, не турбуючись про деталі фону, наприклад, що встановлена ​​версія (якщо така є).


Хіба це не був би лише шаблон адаптера?
Чарльз Грехем

1
Веб-сервіс споживається проксі, тоді як шаблон адаптера використовується більше для перетворення або перекладу даних з однієї форми в іншу.
hmcclungiii

1

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

Однак у випадку проксі, що додає об'єкт, може відтворити деякі методи самостійно, він просто ініціалізує цільовий об’єкт, коли клієнт викликає деякі методи, необхідні йому цільовому об'єкту, і це лінива ініціалізація. У випадку інших шаблонів об'єкт, що вкладається, практично ґрунтується на цільовому об'єкті. Тому цільовий об'єкт завжди ініціалізується разом із об'єктом, що вкладається в конструктори / сеттери.

Інша справа, проксі-сервер робить саме те, що робить ціль, тоді як інші шаблони додають більше функціональності для націлювання.


1

Я хотів би додати приклади до відповіді Білла Карвінга (що це чудово. Доречно). Я також додаю деякі ключові відмінності в реалізації, які, на мою думку, відсутні

Цитовані частини - з відповіді [ https://stackoverflow.com/a/350471/1984346] (Білл Карвінг)

Проксі, декоратор, адаптер та міст - це всі варіанти "обгортання" класу. Але їх використання різне.

  • Проксі-сервер можна використовувати, коли ви хочете ліниво встановити об'єкт або приховати той факт, що ви викликаєте віддалену службу або контролюєте доступ до об'єкта.

ProxyClass і ObjectClass, який є проксі-сервером, повинні реалізовувати один і той же інтерфейс, щоб вони були взаємозамінними

Приклад - дорогий проксі-об'єкт

class ProxyHumanGenome implements GenomeInterface  {
    private $humanGenome = NULL; 

    // humanGenome class is not instantiated at construct time
    function __construct() {
    }

    function getGenomeCount() {
        if (NULL == $this->humanGenome) {
            $this->instantiateGenomeClass(); 
        }
        return $this->humanGenome->getGenomeCount();
    }
} 
class HumanGenome implement GenomeInterface { ... }
  • Декоратор також називається "Smart Proxy". Це використовується, коли ви хочете додати функціональність об'єкту, але не шляхом розширення його типу. Це дозволяє зробити це під час виконання.

DecoratorClass повинен (міг) реалізувати розширений інтерфейс ObjectClass. Тож ObjectClass можна було б замінити DecoratorClass, але не навпаки.

Приклад - додавання функціональності додавання

class DecoratorHumanGenome implements CheckGenomeInterface  {

    // ... same code as previous example

    // added functionality
    public function isComplete() {
        $this->humanGenome->getCount >= 21000
    }
}

interface CheckGenomeInterface extends GenomeInterface {

    public function isComplete();

}

class HumanGenome implement GenomeInterface { ... }
  • Адаптер використовується, коли у вас є абстрактний інтерфейс, і ви хочете зіставити цей інтерфейс на інший об'єкт, який має аналогічну функціональну роль, але інший інтерфейс.

Відмінності в реалізації Проксі, декоратор, адаптер

Адаптер забезпечує інший інтерфейс для свого предмета. Проксі надає той же інтерфейс. Decorator забезпечує розширений інтерфейс.

  • Bridge дуже схожий на Adapter, але ми називаємо його Bridge, коли ви визначаєте як абстрактний інтерфейс, так і базову реалізацію. Тобто ви не пристосовуєтесь до якогось застарілого чи стороннього коду, ви є дизайнером всього коду, але вам потрібно мати можливість замінювати різні реалізації.

  • Фасад - це інтерфейс вищого рівня (читай: простіший) для підсистеми одного або декількох класів. Припустимо, у вас є складна концепція, для якої потрібно представити кілька об'єктів. Внесення змін до цього набору об’єктів заплутано, оскільки ви не завжди знаєте, який об’єкт має метод, який потрібно викликати. Настав час написати Фасад, який надає методи високого рівня для всіх складних операцій, які Ви можете зробити для колекції об’єктів. Приклад: Модель предметної області для шкільної секції, з допомогою методів , таких як countStudents(), reportAttendance(), assignSubstituteTeacher(), і так далі.

Більшість інформації у цій відповіді походить з https://sourcemaking.com/design_patterns , що я рекомендую як відмінний ресурс для моделей дизайну.


0

Я вважаю, що код дасть чіткі ідеї (щоб доповнити інші відповіді). Дивіться нижче, (Фокусуйте типи, які клас реалізує та завершує)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}

-3

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

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


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