Chuyển đến nội dung chính

Design Pattern: Chain of Responsibility

Bạn nhận được 1 request và bạn có 1 loạt các hàm có khả năng xử lý request đó. Bạn có thể dùng switch, if-else. Sẽ rất phức tạp nếu số lượng hàm tăng lên, chưa kể đến việc khách hàng thay đổi yêu cầu như cơm bữa. Để giải quyết vấn đề này, bạn hãy xem qua Chain Of Responsibility pattern.

 Định nghĩa

Avoid coupling the senderof a request to itsreceiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
Mẫu Chain of Responsiblity dùng để tránh sự liên kết trực tiếp giữa đối tượng gửi yêu cầu và đối tượng nhận yêu cầu khi yêu cầu có thể đựơc xử lý bởi hơn một đối tượng. Móc nối các đối tượng nhận yêu cầu thành một chuỗi và gửi yêu cầu theo chuỗi đó cho đến khi có một đối tượng xử lý nó.

Sơ đồ UML


Handler:
  • Định nghĩa 1 interface để xử lý các yêu cầu.
  • (Tùy chọn) Gán giá trị cho đối tượng successor.
ConcreteHandler:
  • Xử lý yêu cầu.
  • Có thể truy cập đối tượng successor (thuộc class Handler)
  • Nếu đối tượng ConcreateHandler không thể xử lý được yêu cầu, nó sẽ gởi lời yêu cầu cho successor của nó.
Hiểu đơn giản: Bạn có 1 chuỗi các hành động. Khi nhận request, bạn cho A xử lý. Nếu A không thể xử lý, A sẽ gọi A.successor.HandleRequest(request) ~ B.HandleRequest(request). Cứ tiếp tục cho đến khi request được xử lý hoặc không còn HandlerConcrete nào để xử lý (successor = null).

Ưu điểm:

  • Giảm kết nối. Thay vì một đối tượng có khả năng xử lý yêu cầu chứa tham chiếu đến tất cả các đối tượng khác, nó chỉ cần một tham chiếu đến đối tượng tiếp theo.
  • Tăng tính linh hoạt và phân chia trách nhiệm cho các đối tượng.
  • Có khả năng thay đổi dây chuyền trong thời gian chạy.
  • Không đảm bảo có đối tượng xử lý yêu cầu.

Ví dụ

Để có tiền mua đồ chơi, đứa bé xin tiền anh hai nó, anh hai nó không đủ tiền, chuyển lời yêu cầu tới mẹ nó, mẹ nó cũng không đủ tiền, gởi lời yêu cầu cho ba nó. Nếu ba nó không đủ tiền thì lời yêu cầu sẽ không thực hiện. Ngược lại, ba nó sẽ thực hiện yêu cầu.

Lớp Handler

    public abstract class Approver
    {
        protected Approver Successor;

        public abstract void HandleRequest(int money);

        public void Next(Approver nextApprover)
        {
            Successor = nextApprover;
        }
    }

Lớp Concreate Handler

    public class BrotherApproval: Approver
    {
        public override void HandleRequest(int money)
        {
            if (money < 50)
            {
                Console.WriteLine("{0} handled request {1}k", GetType().Name, money);
            }
            else
            {
                if (Successor != null)
                    Successor.HandleRequest(money);
            }
        }
    }
    public class MotherApproval: Approver
    {
        public override void HandleRequest(int money)
        {
            if (money < 100)
            {
                Console.WriteLine("{0} handled request {1}k", GetType().Name, money);
            }
            else
            {
                if (Successor != null)
                    Successor.HandleRequest(money);
            }
        }
    }
    public class FatherApproval: Approver
    {
        public override void HandleRequest(int money)
        {
            if (money < 200)
            {
                Console.WriteLine("{0} handled request {1}k", GetType().Name, money);
            }
            else
            {
                if(Successor != null)
                    Successor.HandleRequest(money);
            }
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            var money = new List<int> { 3, 30, 60, 100, 200, 500 };
            Approver brotherApproval = new BrotherApproval();
            Approver motherApproval = new MotherApproval();
            Approver fatherApproval = new FatherApproval();
            brotherApproval.Next(motherApproval);
            motherApproval.Next(fatherApproval);
            foreach (var i in money)
            {
                Console.WriteLine("Request {0}k", i);
                brotherApproval.HandleRequest(i);
            }
        }
    }

Ứng dụng

Chúng ta sử dụng mẫu Chain of Responsibility trong các trường hợp sau :
  • Có nhiều hơn một đối tượng có khả thực xử lý một yêu cầu trong khi đối tượng cụ thể nào xử lý yêu cầu đó lại phụ thuộc vào ngữ cảnh sử dụng.
  • Muốn gửi yêu cầu đến một trong số vài đối tượng nhưng không xác định đối tượng cụ thể nào sẽ xử lý yêu cầu đó.
  • Tập các đối tượng có khả năng xử lý yêu cầu là một tập biến đổi.

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.