В нашем предыдущем блоге мы обсуждали необходимость свободного наследования компоновщика, а также преимущества периодического расширения существующего компоновщика при соблюдении принципов SOLID (т. е. с использованием принципа Open-Closed). Здесь мы поговорим об очень уникальной ситуации со сборщиками, которые могут пригодиться, когда требуется поэтапное создание объекта.
Давайте рассмотрим пример: в нашем предыдущем блоге мы создали класс Сотрудник, но теперь требования изменились, и мы должны установить зарплату на основе назначения, поэтому взгляните на наш новый класс Сотрудник.
public enum Designations { Employee, Manager, TechnicalLead } public class Employee { public Guid Id { get; set; } public Designations Designation { get; set; } public decimal Salary { get; set; } } public class EmployeeBuilder { private Employee _employee = new Employee(); public EmployeeBuilder Create(Designations desg, decimal salary) { _employee = new Employee { Id = Guid.NewGuid(), Designation = desg, Salary = salary }; return this; } public Employee Build() { return _employee; } }
Приведенный выше пример удовлетворит наши основные потребности в создании объектов, но в коде есть очень существенный недостаток. В настоящее время мы предоставляем пользователю метод Create(), и хотя мы принимаем как назначение сотрудника, так и его оклад, что произойдет, если пользователь введет неверные назначение и оклад? Поскольку пользователь должен беспокоиться о бизнес-логике, это решение не кажется идеальным. Другое дело, что мы не должны позволять пользователям устанавливать зарплату; вместо этого оно должно быть установлено как свойство в соответствии с нашей бизнес-логикой. Вы можете задаться вопросом, что нужно сделать, чтобы исправить это, и ответ очень прост: мы можем использовать Stepwise Builder, чтобы закрыть любую лазейку, которая в настоящее время присутствует.
namespace Builder.StepwiseBuilder { public enum Designations { Employee, Manager, TechnicalLead } public interface IDesignationBuilder { ISalaryBuilder WithDesignation(Designations designation); } public interface ISalaryBuilder { IEmployeeBuilder AssignSalary(); } public interface IEmployeeBuilder { Employee Build(); } public class Employee { public Guid Id { get; set; } public Designations Designation { get; set; } public decimal Salary { get; set; } public static Builder CreateBuilder() { return new Builder(); } public class Builder : IDesignationBuilder, ISalaryBuilder, IEmployeeBuilder { private Employee _employee = new Employee(); public ISalaryBuilder WithDesignation(Designations designation) { _employee.Designation = designation; return this; } public IEmployeeBuilder AssignSalary() { switch (_employee.Designation) { case Designations.Employee: _employee.Salary = 1000; break; case Designations.Manager: _employee.Salary = 5000; break; case Designations.TechnicalLead: _employee.Salary = 10000; break; default: throw new InvalidOperationException("Designation not supported, please pass valid designation"); } return this; } public Employee Build() { return _employee; } } } public class StepWiseBuilderExample { public static void Main(string[] args) { var employee = Employee.CreateBuilder() .WithDesignation(Designations.Employee) .AssignSalary() .Build(); Console.WriteLine($"{employee.Designation} gets paid ${employee.Salary}"); } } }
Здесь мы используем разные интерфейсы для разных целей, а затем создаем цепочку, чтобы выполнять операции на определенных этапах. Как видите, IDesignationBuilder возвращает ISalaryBuilder и т. д., так что мы можем выполнять операции, связанные с окладом, только после установки назначения. Таким образом, мы непреднамеренно заставляем пользователей выполнять шаги, а также следим за соблюдением бизнес-логики.
Наконец, я просто хотел подчеркнуть, насколько важен этот тип Builder и как его можно использовать во многих различных контекстах, особенно при выполнении предметно-ориентированного программирования, когда вам нужно убедиться, что объекты создаются с определенной целью и что пользователи следуют инструкциям. надлежащие процедуры для создания объектов.
Так что это все для этого сообщения в блоге. В нашем следующем блоге мы рассмотрим другие способы реализации сборщиков и поговорим о некоторых их приложениях. До тех пор.
Удачного кодирования…!!!