Builder Pattern in C#
Bài đăng này đã không được cập nhật trong 6 năm
Giới thiệu
Trong bài trước thì mình đã giới thiệu về "Abstract Factory Pattern in C#", hôm nay thì mình xin tiếp tục giới thiệu về 1 pattern trong "Creational Patterns", đó chính là Builder Pattern.
Định nghĩa
Builder Pattern chia cấu trúc của 1 object phức tạp từ những chi tiết nhỏ của nó, vì vậy 1 xứ lý giống nhau có thể tạo ra những object với chi tiết khác nhau (nhờ những builder khác nhau) Độ sử dụng thường xuyên: Bình thường Để hiểu rõ hơn về pattern này thì chúng ta sẽ cùng xem giải thích và ví dụ nhé.
UML Diagram
Các thành phần
Các class và object tham gia vào pattern này bao gồm:
- Builder (VehicleBuilder) cụ thế hóa 1 abstract interface bằng cách tạo ra 1 phần của Product object
- ConcreteBuilder (MotorCycleBuilder, CarBuilder, ScooterBuilder)
- cấu trúc và ghép nối các phần của 1 product bằng cách implement Builder interface
- định nghĩa lại và ghi lại những chi tiết mà nó tạo ra
- đưa ra 1 interface để có thể trả về chi tiết product tạo ra
- Director (Shop) tạo ra object sử dụng Builder interface
- Product (Vehicle) chính là object phức tạp được tạo ra. ConcreteBuilder xây dựng chi tiết sản phẩm bên trong và định nghĩa việc xử lý ghép nối, gồm các class định nghĩa các chi tiết, và các interface để ghép nối các phần tạo ra kết quả cuối cùng.
Cấu trúc code trong C#
using System;
using System.Collections.Generic;
namespace DoFactory.GangOfFour.Builder.Structural
{
/// <summary>
/// MainApp startup class for Structural
/// Builder Design Pattern.
/// </summary>
public class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
// Create director and builders
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
// Construct two products
director.Construct(b1);
Product p1 = b1.GetResult();
p1.Show();
director.Construct(b2);
Product p2 = b2.GetResult();
p2.Show();
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Director' class
/// </summary>
class Director
{
// Builder uses a complex series of steps
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
/// <summary>
/// The 'Builder' abstract class
/// </summary>
abstract class Builder
{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
}
/// <summary>
/// The 'ConcreteBuilder1' class
/// </summary>
class ConcreteBuilder1 : Builder
{
private Product _product = new Product();
public override void BuildPartA()
{
_product.Add("PartA");
}
public override void BuildPartB()
{
_product.Add("PartB");
}
public override Product GetResult()
{
return _product;
}
}
/// <summary>
/// The 'ConcreteBuilder2' class
/// </summary>
class ConcreteBuilder2 : Builder
{
private Product _product = new Product();
public override void BuildPartA()
{
_product.Add("PartX");
}
public override void BuildPartB()
{
_product.Add("PartY");
}
public override Product GetResult()
{
return _product;
}
}
/// <summary>
/// The 'Product' class
/// </summary>
class Product
{
private List<string> _parts = new List<string>();
public void Add(string part)
{
_parts.Add(part);
}
public void Show()
{
Console.WriteLine("\nProduct Parts -------");
foreach (string part in _parts)
Console.WriteLine(part);
}
}
}
Kết quả
Product Parts -------
PartA
PartB
Product Parts -------
PartX
PartY
Cấu trúc code trong dự án thực tế
using System;
using System.Collections.Generic;
namespace DoFactory.GangOfFour.Builder.RealWorld
{
/// <summary>
/// MainApp startup class for Real-World
/// Builder Design Pattern.
/// </summary>
public class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
VehicleBuilder builder;
// Create shop with vehicle builders
Shop shop = new Shop();
// Construct and display vehicles
builder = new ScooterBuilder();
shop.Construct(builder);
builder.Vehicle.Show();
builder = new CarBuilder();
shop.Construct(builder);
builder.Vehicle.Show();
builder = new MotorCycleBuilder();
shop.Construct(builder);
builder.Vehicle.Show();
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Director' class
/// </summary>
class Shop
{
// Builder uses a complex series of steps
public void Construct(VehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
}
}
/// <summary>
/// The 'Builder' abstract class
/// </summary>
abstract class VehicleBuilder
{
protected Vehicle vehicle;
// Gets vehicle instance
public Vehicle Vehicle
{
get { return vehicle; }
}
// Abstract build methods
public abstract void BuildFrame();
public abstract void BuildEngine();
public abstract void BuildWheels();
public abstract void BuildDoors();
}
/// <summary>
/// The 'ConcreteBuilder1' class
/// </summary>
class MotorCycleBuilder : VehicleBuilder
{
public MotorCycleBuilder()
{
vehicle = new Vehicle("MotorCycle");
}
public override void BuildFrame()
{
vehicle["frame"] = "MotorCycle Frame";
}
public override void BuildEngine()
{
vehicle["engine"] = "500 cc";
}
public override void BuildWheels()
{
vehicle["wheels"] = "2";
}
public override void BuildDoors()
{
vehicle["doors"] = "0";
}
}
/// <summary>
/// The 'ConcreteBuilder2' class
/// </summary>
class CarBuilder : VehicleBuilder
{
public CarBuilder()
{
vehicle = new Vehicle("Car");
}
public override void BuildFrame()
{
vehicle["frame"] = "Car Frame";
}
public override void BuildEngine()
{
vehicle["engine"] = "2500 cc";
}
public override void BuildWheels()
{
vehicle["wheels"] = "4";
}
public override void BuildDoors()
{
vehicle["doors"] = "4";
}
}
/// <summary>
/// The 'ConcreteBuilder3' class
/// </summary>
class ScooterBuilder : VehicleBuilder
{
public ScooterBuilder()
{
vehicle = new Vehicle("Scooter");
}
public override void BuildFrame()
{
vehicle["frame"] = "Scooter Frame";
}
public override void BuildEngine()
{
vehicle["engine"] = "50 cc";
}
public override void BuildWheels()
{
vehicle["wheels"] = "2";
}
public override void BuildDoors()
{
vehicle["doors"] = "0";
}
}
/// <summary>
/// The 'Product' class
/// </summary>
class Vehicle
{
private string _vehicleType;
private Dictionary<string,string> _parts =
new Dictionary<string,string>();
// Constructor
public Vehicle(string vehicleType)
{
this._vehicleType = vehicleType;
}
// Indexer
public string this[string key]
{
get { return _parts[key]; }
set { _parts[key] = value; }
}
public void Show()
{
Console.WriteLine("\n---------------------------");
Console.WriteLine("Vehicle Type: {0}", _vehicleType);
Console.WriteLine(" Frame : {0}", _parts["frame"]);
Console.WriteLine(" Engine : {0}", _parts["engine"]);
Console.WriteLine(" #Wheels: {0}", _parts["wheels"]);
Console.WriteLine(" #Doors : {0}", _parts["doors"]);
}
}
}
Kết quả:
---------------------------
Vehicle Type: Scooter
Frame : Scooter Frame
Engine : none
#Wheels: 2
#Doors : 0
---------------------------
Vehicle Type: Car
Frame : Car Frame
Engine : 2500 cc
#Wheels: 4
#Doors : 4
---------------------------
Vehicle Type: MotorCycle
Frame : MotorCycle Frame
Engine : 500 cc
#Wheels: 2
#Doors : 0
Kết luận
Builder Pattern có mức độ sử dụng vừa phải và các bạn nên cân nhắc sử dụng để có thể làm cho code sạch sẽ và dễ nhìn. Cảm ơn các bạn đã đọc bài. Bài viết tham khảo từ nguồn: http://www.dofactory.com/net/builder-design-pattern
All rights reserved