Builder Pattern in C#



  • 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
    Nguồn: Viblo



Có vẻ như bạn đã mất kết nối tới LaptrinhX, vui lòng đợi một lúc để chúng tôi thử kết nối lại.