Fluent builder (шаблон проєктування)Fluent builder — твірний шаблон проєктування, який спрощує процес створення об'єктів. МотиваціяСпростити процес створення важких об'єктів. Розв'язує проблему перевантажених конструкторів, а також проблему великої кількості аргументів в конструкторах. ОписНехай дано клас User public class User
{
// FIELDS
private string name;
private string surname;
private int age;
private bool isMarried;
// CONSTRUCTORS
public User()
{
this.name = string.Empty;
this.surname = string.Empty;
this.age = 18;
this.isMarried = false;
}
public User(string name, string surname, int age, bool isMarried)
{
this.name = name;
this.surname = surname;
this.age = age > 18 ? age : 18;
this.isMarried = isMarried;
}
}
Його конструктор приймає чотири аргументи, що вже здається надлишковістю. Крім того кількість полів та аргументів може бути значно більшою, а для полів можуть бути присутні різноманітні перевірки. Додамо клас, який буде відповідати за побудову нашого об'єкта public class UserBuilder
{
// FIELDS
private User user;
// CONSTRUCTORS
public UserBuilder()
{
user = new User();
}
// METHODS
public UserBuilder SetName(string name)
{
user.name = name;
return this;
}
public UserBuilder SetSurname(string surname)
{
user.surname = surname;
return this;
}
public UserBuilder SetAge(int age)
{
user.age = age > 18 ? age : 18;
return this;
}
public UserBuilder SetIsMarried(bool isMerried)
{
user.isMarried = isMerried;
return this;
}
// BUILDING
public User Build()
{
return user;
}
}
Цей клас вміє лише будувати нашого User'a. Важливо відмітити, що кожний Set метод повертає this, тобто посилання на об'єкт будівельника. Це дозволить нам використати Fluent interface. User user = new User.UserBuilder()
.SetName("John")
.SetSurname("Doe")
.Build();
Звісно це не є обов'язковою вимогою шаблону. Переваги та недолікиПереваги
Недоліки
Зв'язок з іншими патернами
РеалізаціяC#Приклад реалізації на мові С#
namespace FluentBuilder
{
public class User
{
// FIELDS
private string name;
private string surname;
private int age;
private bool isMarried;
// CONSTRUCTORS
public User()
{
this.name = string.Empty;
this.surname = string.Empty;
this.age = 18;
this.isMarried = false;
}
public User(string name, string surname, int age, bool isMarried)
{
this.name = name;
this.surname = surname;
this.age = age > 18 ? age : 18;
this.isMarried = isMarried;
}
public static UserBuilder CreateBuilder()
{
return new UserBuilder();
}
// INNER CLASSES
public class UserBuilder
{
// FIELDS
private User user;
// CONSTRUCTORS
public UserBuilder()
{
user = new User();
}
// METHODS
public UserBuilder SetName(string name)
{
user.name = name;
return this;
}
public UserBuilder SetSurname(string surname)
{
user.surname = surname;
return this;
}
public UserBuilder SetAge(int age)
{
user.age = age > 18 ? age : 18;
return this;
}
public UserBuilder SetIsMarried(bool isMerried)
{
user.isMarried = isMerried;
return this;
}
// BUILDING
public User Build()
{
return user;
}
public static implicit operator User(UserBuilder builder)
{
return builder.user;
}
}
}
class Program
{
static void Main(string[] args)
{
// different ways of creating a builder
// user builder's constructor
User user1 = new User.UserBuilder()
.SetName("John")
.SetSurname("Doe")
.Build();
// user's static method
User user2 = User.CreateBuilder()
.SetName("John")
.SetSurname("Doe")
.Build();
// different ways of building user
// build method
User user3 = new User.UserBuilder()
.SetName("John")
.SetSurname("Doe")
.Build();
// conversion
User user4 = new User.UserBuilder()
.SetName("John")
.SetSurname("Doe");
System.Console.Read();
}
}
}
Див.такожДжерела
|