Дизайн патерн Builder - конструктор на максималках

Поделиться
HTML-код
  • Опубликовано: 18 окт 2024

Комментарии • 9

  • @apalyukha
    @apalyukha 11 месяцев назад

    О шаблони проєктування, а потім і про SOLID можливо щось буде Дякую.

    • @FoxOwlet-IT
      @FoxOwlet-IT  11 месяцев назад +1

      Так, до SOLIDу теж колись руки дійдуть_)

  • @viktors.4844
    @viktors.4844 11 месяцев назад

    Привіт, дякую за відео. В мене питання.
    Пару місяців тому я експериментував/освоював білдер, находив різні приклади і вони виглядять як і в тебе(або ломбок), але я реалізував(сам дійшов) до іншого вигляду, і я розумію що тут всі праві а я щось пропускаю бо я бачу переваги(не бачу недоліків) свого білдера над іншим.
    Реалізація : private User(){}; private String name="Default Name"; public static class UserBuilder{ private User that; public UserBuilder(){ that=new User(); } UserBuilder name(String name){ that.name=name; return this; } User build(){ return that; }
    Переваги : 1) завжди є значення за замовченням. 2) не дублюються поля, в білдері їх зазвичай багато, а коли і юзерів багато то бере це памяті не мало.
    Що саме я пропускаю? Дякую.

    • @FoxOwlet-IT
      @FoxOwlet-IT  11 месяцев назад +1

      Привіт
      TL;DR; З точки зору теорії - такий білдер програє за рахунок того, що юзер має бути мутабельним. З точки зору практики - в більшості випадків юзер і так буде мутабельним, тому це не проблема
      Ну і плюс цей білдер одноразовий, його інстанс не можна безпечно перевикористати
      Розгорнуто: Ось такий білдер простіший, так. Але є нюанс. Об'єкт, який створюється - потенційно мутабельний. В гіршому випадку в нас буде публічний сеттер (окей, хібернейт і інші фреймворки, які вимагають сеттер - окрема тема). А білдер дозволяє тримати мутабельний стан окремо від об'єкту, який він створює. Відповідно, у нас є гарантія, що після створення об'єкт вже не зміниться. А з іммутабельними об'єктами працювати простіше, вони безпечніші і призводять до меншої кількості проблем, особливо в багатопоточному середовищі.
      Це можна виправити приватним сеттером (ну або сетити в поле, що практично те саме). Або package-private сеттер. Суть та ж сама, просто потенційно більше класів можуть мати доступ до стану, це якось не по-ООПшному
      Проблема номер два. Стан об'єкту по суті зберігається в білдері. Якщо використати інстанс цього білдера для створення двох об'єктів... Результат навряд буде очікуваним - старий об'єкт теж зміниться. А це може бути не дуже приємно дебажити. Хороший білдер має або повертати новий об'єкт кожен раз, або бути одноразовим і при другому зверненні кидати ексепшн
      Але є простий варіант, як позбавити останньої проблеми твій білдер
      public User build() {
      User result = that;
      that = new User();
      return result;
      }
      Але все ще лишається проблема потенційної мутабельності юзера
      Сказати, що це проблема - важко, бо, знов таки, хібернейт вміє працювати лише з мутабельними сутностями. Тому хочеш-не хочеш, а публічний сеттер робити доведеться (ну, не беремо до увагі ті унікальні проекти, де джава юзається без спрінга і хібера)
      Тут (з хібером) такий білдер скоріше має право на життя
      Білдер, який дублює стан (знов таки, в теорії) безпечніший. А ломбок якраз і "хороший" тим, що приховує це дублювання від нас. А оскільки він код генерує сам, нам не треба синхронізувати наші зміни в двох класах. Тому по суті дублювання є лише в результуючому коді, але не в сорцях. Відповідно, ніяких проблем, які властиві дублюванню коду, це не несе

    • @viktors.4844
      @viktors.4844 11 месяцев назад

      @@FoxOwlet-ITДякую за таку розгорнуту відповідь, осягнув поки не все але зачерпнув багато. Ще мабуть "вузьке місце" щоб від створення that аж до методу build() цей стан що зберігається в білдері не змінувався де інде(в іншому потоці). Короче все воно добре "звідси аж до.. " потрібно знати де і коли використовувати і коли є своя реалізація можуть бути свої(не очевидні для гугла наприклад) проблеми/виключення. 👍

    • @FoxOwlet-IT
      @FoxOwlet-IT  11 месяцев назад

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

    • @viktors.4844
      @viktors.4844 11 месяцев назад

      @@FoxOwlet-IT доречі, зараз подивився як я там тоді писав, я писав без сеттерів (внутрішній статичний клас бачить приватні поля, коли писав не задумовувався тому і перевірив зараз).