Design-Patterns

Mediator

Khái Niệm

Mediator Pattern, trong lĩnh vực phát triển phần mềm, là một mẫu thiết kế hành vi. Nó giúp giảm sự phức tạp trong giao tiếp giữa nhiều đối tượng hoặc lớp bằng cách cung cấp một đối tượng trung gian, gọi là ‘mediator’. Điều này giúp các đối tượng không giao tiếp trực tiếp với nhau, mà thông qua mediator, từ đó giảm thiểu sự phụ thuộc lẫn nhau và làm cho mã nguồn dễ bảo trì hơn.

Tổng quan

Đặt vấn đề

Giải pháp

classDiagram
    class Mediator {
        <<interface>>
        +notify(sender, event)
    }
    class ConcreteMediator {
        +notify(sender, event)
    }
    class BaseComponent {
        +mediator
    }
    class Component1 {
        +doA()
        +doB()
    }
    class Component2 {
        +doC()
        +doD()
    }

    Mediator <|.. ConcreteMediator
    BaseComponent o-- Mediator : has
    Component1 --|> BaseComponent
    Component2 --|> BaseComponent
    ConcreteMediator o-- Component1
    ConcreteMediator o-- Component2

Cấu trúc

classDiagram
    class Mediator {
        <<interface>>
        +registerColleague(Colleague)
        +sendMessage()
    }
    class Colleague {
        -Mediator mediator
        +receiveMessage()
    }
    class ConcreteMediator {
        +sendMessage()
        +addColleague(Colleague)
    }
    class ConcreteColleague1 {
        +receiveMessage()
    }
    class ConcreteColleague2 {
        +receiveMessage()
    }

    Mediator <|.. ConcreteMediator
    Colleague <|.. ConcreteColleague1
    Colleague <|.. ConcreteColleague2
    Mediator o-- Colleague : communicates
    ConcreteMediator --|> Mediator
    ConcreteColleague1 --|> Colleague
    ConcreteColleague2 --|> Colleague

Cách triển khai

Trong ví dụ này, ConcreteMediator quản lý thông điệp giữa các Colleague. Mỗi ConcreteColleague sẽ gửi và nhận thông điệp thông qua Mediator, giúp giảm sự phụ thuộc trực tiếp giữa các đối tượng Colleague.

Bước 1: Tạo Interface Mediator

public interface Mediator {
    void registerColleague(Colleague colleague);
    void sendMessage(String message, Colleague originator);
}

Bước 2: Tạo Class Abstract Colleague

public abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void receiveMessage(String message);
}

Bước 3: Tạo Class ConcreteMediator

import java.util.ArrayList;
import java.util.List;

public class ConcreteMediator implements Mediator {
    private List<Colleague> colleagues;

    public ConcreteMediator() {
        this.colleagues = new ArrayList<>();
    }

    @Override
    public void registerColleague(Colleague colleague) {
        colleagues.add(colleague);
    }

    @Override
    public void sendMessage(String message, Colleague originator) {
        for (Colleague colleague : colleagues) {
            // Don't notify the originator
            if (colleague != originator) {
                colleague.receiveMessage(message);
            }
        }
    }
}

Bước 4: Tạo Class ConcreteColleague1ConcreteColleague2

public class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println("ConcreteColleague1 received: " + message);
    }
}

public class ConcreteColleague2 extends Colleague {
    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println("ConcreteColleague2 received: " + message);
    }
}

Bước 5: Demo Sử Dụng

public class Main {
    public static void main(String[] args) {
        Mediator mediator = new ConcreteMediator();

        Colleague colleague1 = new ConcreteColleague1(mediator);
        Colleague colleague2 = new ConcreteColleague2(mediator);

        mediator.registerColleague(colleague1);
        mediator.registerColleague(colleague2);

        colleague1.receiveMessage("Hello from Colleague1");
        colleague2.receiveMessage("Hello from Colleague2");
    }
}

Ví dụ

Mediator Pattern là một mẫu thiết kế hành vi giúp giảm sự phức tạp trong giao tiếp giữa các đối tượng hoặc lớp bằng cách cung cấp một lớp trung gian, gọi là “mediator”. Mediator này kiểm soát cách thức giao tiếp giữa các đối tượng và hỗ trợ việc loại bỏ sự phụ thuộc lẫn nhau giữa chúng, làm cho mã nguồn dễ quản lý và bảo trì hơn.

Trong ví dụ sau, chúng ta xây dựng một hệ thống chat đơn giản, trong đó các người dùng (User) gửi tin nhắn cho nhau thông qua một Mediator là Server. Mỗi người dùng không trực tiếp giao tiếp với người dùng khác, mà thông qua Server. Điều này giúp dễ dàng thay đổi hoặc mở rộng logic giao tiếp mà không cần thay đổi trong các lớp người dùng.

classDiagram
    class User {
        +String name
        +sendMessage(String)
        +receiveMessage(String)
    }

    class Server {
        +registerUser(User)
        +sendMessage(User, String)
    }

    User "1" <-- "1" Server : mediates
  1. Mediator Interface và Concrete Mediator: Đầu tiên, ta định nghĩa interface ChatMediator và lớp cụ thể ChatServer thực thi nó.

     interface ChatMediator {
         void sendMessage(String msg, User user);
         void registerUser(User user);
     }
    
     class ChatServer implements ChatMediator {
         private List<User> users;
    
         public ChatServer() {
             this.users = new ArrayList<>();
         }
    
         @Override
         public void registerUser(User user) {
             users.add(user);
         }
    
         @Override
         public void sendMessage(String msg, User user) {
             for (User u : users) {
                 // message should not be received by the user sending it
                 if (u != user) {
                     u.receiveMessage(msg);
                 }
             }
         }
     }
    
  2. Colleague Classes: Tiếp theo, ta tạo lớp User mô tả các thành viên tham gia vào hệ thống chat.

     class User {
         private String name;
         private ChatMediator mediator;
    
         public User(String name, ChatMediator med) {
             this.name = name;
             this.mediator = med;
         }
    
         public void sendMessage(String msg) {
             System.out.println(this.name + ": Sending Message = " + msg);
             mediator.sendMessage(msg, this);
         }
    
         public void receiveMessage(String msg) {
             System.out.println(this.name + ": Received Message = " + msg);
         }
     }
    
  3. Sử dụng Mediator Pattern: Cuối cùng, ta tạo các đối tượng User và Server và thử nghiệm giao tiếp giữa chúng.

     public class ChatClient {
         public static void main(String[] args) {
             ChatMediator mediator = new ChatServer();
    
             User user1 = new User("Alice", mediator);
             User user2 = new User("Bob", mediator);
    
             mediator.registerUser(user1);
             mediator.registerUser(user2);
    
             user1.sendMessage("Hi Bob!");
             user2.sendMessage("Hey Alice!");
         }
     }
    

Trong đoạn code trên, ChatServer đóng vai trò là mediator, quản lý việc gửi tin nhắn giữa các User. Các User không giao tiếp trực tiếp với nhau mà thông qua ChatServer.

Khi nào nên sử dụng Mediator Pattern