Подтвердить что ты не робот

Дизайн-шаблон: Builder

Я искал пример хорошего шаблона Builder (на С#), но не могу найти его либо потому, что я не понимаю шаблон Builder, либо я пытаясь сделать то, что никогда не предназначалось. Например, если у меня есть абстрактные автомобильные и абстрактные методы создания автозапчастей, я должен быть в состоянии отправить все 30 из моих выборов Директору, построить ли он куски, которые мне нужны, а затем построить мой автомобиль. Независимо от того, какой автомобиль, грузовик, полу и т.д. Производится, я должен быть способен "прогнать" его точно таким же образом.

Первая проблема - это, скорее всего, примеры значений жесткого кода для конкретных частей, которые, я думаю, должны исходить из базы данных. Я думал, что идея состоит в том, чтобы отправить мой выбор Директору (из источника данных) и создать застройщик для персонализированного продукта на основе моих данных.

Вторая проблема заключается в том, что я хочу, чтобы методы-конструкторы фактически создавали детали, а затем назначали их продукту, а не передавали строки, а действительно сильно типизировали части продукта.

Например, я хочу создать форму "на лету", имея для меня поля формы изготовления Builder, включая метку, раздел ввода, проверку и т.д. Таким образом, я могу прочитать объект из своего ORM, проверить метаданные объекта, передайте это моему Builder и добавьте вновь созданный результат пользовательского контроля в мою веб-форму.

Однако каждый пример Builder, который я нахожу, имеет только жестко закодированные данные вместо того, чтобы передавать варианты из основного кода в Builder и выталкивать настроенный продукт. Кажется, что это большой статический аргумент. Например, если у меня есть три параметра с 10 вариантами в каждом, я не хочу создавать 30 конкретных методов Builder, я хочу создать только достаточно для создания свойств, требуемых моим продуктом, которые могут быть только тремя.

У меня возникает соблазн, что директор существует только в основном коде. Должен быть способ автоматически определить, какой конкретный метод построения вызывать похожим на полиморфизм и перегрузку метода (хотя это очень плохой пример), а не использовать оператор case в шаблоне. (Каждый раз, когда мне нужно добавить новый тип продукта, мне нужно будет изменить существующего директора, что плохо).

4b9b3361

Ответ 1

Я собираюсь обратиться к примеру С# в статье Wikipedia здесь.

Первая проблема - это, скорее всего, примеры значений жесткого кода для конкретных частей, которые, я думаю, должны исходить из базы данных. Я думал, что идея состоит в том, чтобы отправить мой выбор Директору (из источника данных) и создать застройщик для персонализированного продукта на основе моих данных.

В этом случае у вас будет класс, реализующий PizzaBuilder, который знает, как извлекать данные из базы данных. Вы можете сделать это несколькими способами.

Можно было бы сделать HawaiianPizzaBuilder. Когда класс инициализирует, он запрашивает базу данных для гавайской пиццы и извлекает строку. Затем, когда вызываются различные методы Build (x), он будет устанавливать свойства в соответствующее поле строки извлеченной базы данных.

Другим будет просто создание PizzaDatabaseBuilder и убедитесь, что при инициализации класса вы передаете ему идентификатор строки, необходимой для этого типа пиццы. Например, вместо

waiter.PizzaBuilder = new HawaiianPizzaBuilder();

Вы используете

waiter.PizzaBuilder = new PizzaDatabaseBuilder("Hawaiian");

Вторая проблема заключается в том, что я хочу, чтобы методы-конструкторы фактически создавали детали, а затем назначали их продукту, а не передавали строки, а действительно сильно типизировали части продукта.

Не должно быть проблем. Для инициализации полей пиццы вам понадобится другой шаблон типа Factory/Builder. Например

вместо

 public override void BuildDough()   { pizza.Dough   = "pan baked"; }

вы бы сделали что-то вроде

 public override void BuildDough()   { pizza.Dough   = new DoughBuilder("pan baked"); }

или

 public override void BuildDough()   { pizza.Dough   = new PanBakedDoughBuilder(); }

DoughBuilder может перейти в другую таблицу вашей базы данных, чтобы правильно заполнить класс PizzaDough.

Ответ 2

В большинстве случаев вызов BuilderPattern выглядит следующим образом:

Car car = new CarBuilder().withDoors(4).withColor("red").withABS(true).build();

Ответ 3

Я никогда не думал об этом таким образом, но LINQ (шаблон, а не синтаксис) на самом деле является строителем, верно?

Это свободный интерфейс, который строит запрос и может создавать запросы в разных представлениях (SQL, запросы объекта памяти, запросы веб-сервисов, Bart de Smet даже написал реализацию Linq-to-Excel).

Ответ 4

Я бы сказал, что вы не можете обойти ни один из них - иметь несколько перегрузок для ваших частей и иметь оператор case/if где-то в стеке. Также вам нужно изменить свой код при добавлении нового класса.

Сказав, что вы можете получить помощь с некоторыми другими паттерами, а именно Factory, которые могут помочь вам в процессе строительства. Также разумное использование полиморфизма (например, все части, наследуемые от какого-либо типа, будь то класс или интерфейс) может уменьшить количество ifs/cases и перегрузок.

Надеюсь, что это поможет.