В Java и C # вы можете создать объект со свойствами, которые можно установить при инициализации, либо определив конструктор с параметрами, определив каждое свойство после создания объекта, либо используя шаблон интерфейса Builder / Fluid. Однако в C # 3 были введены инициализаторы объектов и коллекций, что означало, что шаблон компоновщика был практически бесполезен. На языке без инициализаторов можно реализовать конструктор, а затем использовать его так:
Vehicle v = new Vehicle.Builder()
.manufacturer("Toyota")
.model("Camry")
.year(1997)
.colour(CarColours.Red)
.addSpecialFeature(new Feature.CDPlayer())
.addSpecialFeature(new Feature.SeatWarmer(4))
.build();
И наоборот, в C # можно написать:
var vehicle = new Vehicle {
Manufacturer = "Toyota",
Model = "Camry",
Year = 1997,
Colour = CarColours.Red,
SpecialFeatures = new List<SpecialFeature> {
new Feature.CDPlayer(),
new Feature.SeatWarmer { Seats = 4 }
}
}
... устранение необходимости в сборщике, как показано в предыдущем примере.
Основываясь на этих примерах, по-прежнему ли полезны компоновщики в C # или они полностью заменены инициализаторами?
c#
object-oriented
builder-pattern
svbnet
источник
источник
are builders useful
почему я продолжаю видеть подобные вопросы? Построитель - это шаблон проектирования. Конечно, он может быть представлен как языковая функция, но в конце концов это просто шаблон проектирования. Шаблон дизайна не может быть «неправильным». Это может или не может удовлетворить ваш вариант использования, но это не делает весь шаблон неправильным, только его применение. Помните, что в конце концов шаблоны проектирования решают конкретные проблемы - если вы не столкнулись с проблемой, то зачем вам пытаться ее решить?Ответы:
Как затронуло @ user248215, реальная проблема заключается в неизменности. Причина, по которой вы бы использовали компоновщик в C #, заключается в том, чтобы поддерживать явность инициализатора без необходимости выставления настраиваемых свойств. Это не вопрос инкапсуляции, поэтому я написал свой собственный ответ. Инкапсуляция является довольно ортогональной, так как вызов метода установки не подразумевает того, что фактически делает метод установки, или привязывает вас к его реализации.
В следующей версии C #, 8.0, вероятно, будет введено
with
ключевое слово, которое позволит четко и кратко инициализировать неизменяемые объекты без необходимости написания компоновщиков.Еще одна интересная вещь, которую вы можете сделать со сборщиками, в отличие от инициализаторов, заключается в том, что они могут приводить к различным типам объектов в зависимости от последовательности вызываемых методов.
Например
Просто для пояснения приведенного выше примера, это библиотека сопоставления с образцом, которая использует шаблон построителя для создания «совпадения» путем указания случаев. Случаи добавляются путем вызова
Case
метода, передающего ему функцию. Еслиvalue
присваивается типу параметра функции, он вызывается. Вы можете найти полный исходный код на GitHub и, поскольку XML-комментарии трудно читать в виде простого текста, вот ссылка на встроенную документацию SandCastle (см. Раздел « Замечания »).источник
IEnumerable<Func<T, TResult>>
член.TResult
. В конечном счете, вывод типа был во многом связан с этим. Я также хотел, чтобы он «выглядел» как структура управления. Также я не хотел использовать инициализатор, так как это позволило бы мутации.Инициализаторы объекта требуют, чтобы свойства были доступны вызывающему коду. Вложенные строители могут получить доступ к частным членам класса.
Если вы хотите сделать
Vehicle
неизменяемым (путем установки всех установщиков закрытыми), то для установки приватных переменных можно использовать вложенный конструктор.источник
Все они служат разным целям !!!
Конструкторы могут инициализировать поля, которые отмечены,
readonly
а также частные и защищенные элементы. Однако вы несколько ограничены в том, что вы можете делать внутри конструктора;this
Например, вам следует избегать передачи на любые внешние методы и избегать вызова виртуальных членов, поскольку они могут выполняться в контексте производного класса, который еще не сконструирован. Кроме того, гарантируется, что конструкторы будут работать (если только вызывающая сторона не делает что-то очень необычное), поэтому, если вы задаете поля в конструкторе, код в остальной части класса может предположить, что эти поля не будут нулевыми.Инициализаторы запускаются после построения. Они только позволяют вам называть публичной собственностью; частные и / или только для чтения поля не могут быть установлены. По соглашению, акт установки свойства должен быть довольно ограниченным, например, он должен быть идемпотентным и иметь ограниченные побочные эффекты.
Методы построителя являются реальными методами и поэтому допускают более одного аргумента, и по соглашению могут иметь побочные эффекты, включая создание объекта. Хотя они не могут устанавливать поля только для чтения, они могут делать что-то еще. Кроме того, методы могут быть реализованы как методы расширения (как почти все функциональные возможности LINQ).
источник