Design Patterns - Mediator Pattern

1. Intent

  • Mediator Patern (mô hình trung gian) được sử dụng để giảm sự phức tạp trong "giao tiếp" giữa các lớp và các đối tượng. Mô hình này cung cấp một lớp trung gian có nhiệm vụ xử lý thông tin liên lạc giữa các tầng lớp, hỗ trợ bảo trì mã code dễ dàng bằng cách khớp nối lỏng lẻo.
  • Khớp nối lỏng lẻo ở đây được hiểu là các đối tượng tương đồng không "giao tiếp" trực tiếp với nhau mà giao tiếp thông qua người trung gian, và cho phép bạn thay thay đổi cách tương tác giữa họ một cách độc lập. (phần sau tôi sẽ lấy ví dụ để các bạn dể hiểu hơn).
  • Thúc đẩy mối quan hệ nhiều - nhiều (many-to-many) giữa các đối tượng tượng tương đồng để đạt đến được trạng thái "full object".

2. Example

  • Tháp điều khiển tại sân bay có kiểm soát là một ví dụ về hoạt động của Mediator pattern. Các phi công của các máy bay đang cất cánh hoặc hạ cánh kết nối với tháp chứ không phải giao tiếp rõ ràng với nhau. Những khó khăn về việc ai có thể cất hoặc hạ cánh được thi hành bởi tháp điều khiển. Điều quan trọng cần lưu ý là tháp không kiểm soát toàn bộ chuyến bay. Nó tồn tại chỉ để thực thi các quy định an toàn trong lúc cất và hạ cánh.

3. Structure

Mediator

Mediator để xác định các interface giao tiếp giữa các đối tượng tương đồng.

ConcreteMediator

Thực hiện interface giao tiếp từ Mediator, để điều chỉnh các thông tin liên lạc giữa các đối tượng . Thông báo cho các đối tượng tương đồng đang tồn tại, biết về mục đích giao tiếp.

ConcreteColleague

Thông qua Mediator để giao tiếp với các đối tượng khác.

4. Problem

  • Chúng tôi muốn thiết kế các thành phần có thể tái sử dụng được, nhưng sự phụ thuộc giữa các thành phần có thể tái sử dụng lại cho thấy hiện tượng "spaghetti code" .
  • "Spaghetti code" là một cụm từ khinh bỉ đối với mã nguồn có cấu trúc điều khiển phức tạp và rắc rối, đặc biệt là sử dụng nhiều câu lệnh GOTO, ngoại lệ, luồng hoặc các cấu trúc phân nhánh khác "không có cấu trúc". Nó được đặt tên như vậy bởi vì luồng chương trình được sắp xếp giống như một bát spaghetti, tức là bị xoắn và rối .
  • "Spaghetti code" có thể do nhiều yếu tố, chẳng hạn như việc sửa đổi liên tục của một số người có phong cách lập trình khác nhau trong một thời gian dài. Các chương trình có cấu trúc giảm đáng kể tỉ lệ "spaghetti code".

5. Discussion

  • Trong Unix, quyền truy cập tài nguyên hệ thống được quản lý ở ba cấp độ chi tiết: .. world, group,và owner. Mỗi người dùng trên hệ thống có thể là một thành viên của một hoặc nhiều nhóm, và mỗi nhóm có thể có không hoặc nhiều người dùng được gán cho nó. Ảnh tiếp theo cho thấy ba người dùng được gán cho tất cả ba nhóm.

  • Một ví dụ nơi Mediator rất hữu ích là thiết kế của một người dùng và nhóm các tính năng trong một hệ điều hành. Các mô hình Mediator cung cấp một linh hoạt và cách không xâm lấn để kết hợp và quản lý người dùng trong nhóm.

6. Implementation

  • Chúng tôi đang thể hiện Mediator Pattern bằng ví dụ về phòng chat, nơi có nhiều người dùng có thể gửi tin nhắn đến phòng chat và trách nhiệm của phòng chat hiển thị thông điệp cho tất cả người dùng. Chúng tôi đã tạo ra hai lớp ChatRoom và User. Đối tượng người dùng sẽ sử dụng phương pháp ChatRoom để chia sẻ thông điệp của họ.
  • MediatorPatternDemo, lớp demo của chúng ta, sẽ sử dụng các đối tượng User để hiển thị giao tiếp giữa họ.

Bước 1: Tạo lớp Mediator

import java.util.Date;

public class ChatRoom {
   public static void showMessage(User user, String message){
      System.out.println(new Date().toString() + " [" + user.getName() + "] : " + message);
   }
}

Bước 2: Tạo ra các lớp "đồng nghiệp" (user class)

public class User {
   private String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public User(String name){
      this.name  = name;
   }

   public void sendMessage(String message){
      ChatRoom.showMessage(this,message);
   }
}

Bước 3 : Sử dụng đối tượng User để hiển thị thông tin liên lạc giữa chúng.

public class MediatorPatternDemo {
   public static void main(String[] args) {
      User robert = new User("Robert");
      User john = new User("John");

      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}

Kết quả nhận được :

Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!

Source code tham khảo tại : https://www.tutorialspoint.com/design_pattern/mediator_pattern.htm

7. Applicability

  • Sử dụng Mediator pattern khi :
  1. Một tập các đối tượng giao tiếp theo những cách thức được xác định rõ ràng nhưng cách thức đó quá phức tạp. Sự phụ thuộc lẫn nhau giữa các đối tượng tạo ra kết quả là cách tổ chức không có cấu trúc và khó hiểu.
  2. Tái sử dụng một đối tượng là khó bởi vì nó đề cập đến và giao tiếp với nhiều đối tượng khác.
  3. Điều chỉnh hành vi giữa các lớp một cách dễ dàng, không cần chỉnh sửa ở nhiều lớp.

8. Consequences

Mô hình Mediator có những lợi ích và nhược điểm sau:

  1. Nó giới hạn các lớp con. Một Mediator tập trung một hành vi chung mà nếu không hành vi đó sẽ được phân tán giữa các đối tượng (ví dụ về tháp điều khiển và các máy bay). Thay đổi hành vi này chỉ cần thay đổi lớp Mediator ; các lớp "đồng nghiệp"(Colleague class) có thể không cần thay đổi.
  2. Nó tách riêng các lớp "đồng nghiệp".Mediator khuyến khích sự liên kết lỏng lẻo giữa các đồng nghiệp. Bạn có thể thay đổi và sử dụng lại các lớp đồng nghiệp và Mediator một cách độc lập.
  3. Đơn giản hóa các giao thức đối tượng. Một mediator sẽ thay thế mối quan hệ nhiều- nhiều (many-to-many) giữa các lớp đồng nghiệp bằng quan hệ một- nhiều (one-to-many) giữa mediator và các lớp đồng nghiệp. Quan hệ một-nhiều-dễ hiểu, dễ duy trì và mở rộng.
  4. Nó tóm tắt các đối tượng hợp tác, giao tiếp như thế nào. Điều đó có thể giúp làm rõ các đối tượng tương tác trong hệ thống như thế nào.
  5. Nó tập trung kiểm soát.Mô hình Mediator tạo ra đối tượng hòa giải (mediator) tùy thuộc vào độ phức tạp của các tương tác. Bởi vì một mediator gói các giao thức, nó có thể phức tạp hơn bất kỳ một lớp "đồng nghiệp" nào. Điều này có thể làm cho mediator đó trở thành một khối khó bảo trì.

9. Related Patterns

  • Các mô hình Chain of Responsibility, Command, Mediator, Observer, giải quyết cách bạn có thể tách người gửi và người nhận, nhưng với những sự đánh đổi khác nhau. Chain of Responsibility nhận yêu cầu của người gửi, và gửi yêu cầu đó (request) dọc theo một chuỗi những người nhận tiềm năng (processor). Lệnh thường qui định một kết nối giữa người nhận với người gửi với một phân lớp.Mediator có người gửi và người nhận tham chiếu lẫn nhau một cách gián tiếp. Observer định nghĩa một giao diện tách biệt cho phép nhiều người nhận được cấu hình, thay đổi trong thời gian chạy. Một ví dụ điển hình của Observer là phần "View" của Model-View-Controller.
  • Mediator tương tự như Facade trong đó nó tóm tắt các chức năng của các lớp học hiện có. Tóm tắt của nó là tập trung hoá thông tin giao tiếp giữa các đối tượng "đồng nghiệp", và nó được biết , tham chiếu bởi các đối tượng "đồng nghiệp" (tức là nó định nghĩa một giao thức nhiều chiều). Ngược lại, Facade định nghĩa một giao diện đơn giản hơn cho một hệ thống con, nó không thêm chức năng mới, và không được biết bởi các lớp con của hệ thống con (nghĩa là nó định nghĩa một giao thức đơn hướng, nơi nó yêu cầu các lớp con của hệ thống con thực hiện chứ không có chiều ngược lại).

10. Referenced documents

https://github.com/iluwatar/java-design-patterns/tree/master/mediator https://sourcemaking.com/design_patterns/mediator http://www.itsenka.com/contents/development/designpattern/mediator.html https://www.tutorialspoint.com/design_pattern/mediator_pattern.htm https://en.wikipedia.org/wiki/Spaghetti_code


All Rights Reserved