Builder Pattern in C#
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. 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ý ...
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.
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é.
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(" Product 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(" ---------------------------"); 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
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