设计模式——21. 中介者模式

1. 说明

中介者模式(Mediator Pattern)是一种行为设计模式,它允许对象之间通过一个中介者对象进行通信,而不是直接相互引用。这种模式有助于减少对象之间的直接关联,从而提高系统的可维护性和松耦合性。中介者模式将对象之间的交互集中在一个中介者对象中,该对象负责协调和管理对象之间的通信。
中介者模式通常包含以下角色:

  1. 中介者(Mediator): 中介者是一个接口或抽象类,定义了对象之间通信的协议。
  2. 具体中介者(Concrete Mediator): 具体中介者是实现中介者接口的具体类,它负责实际协调和管理对象之间的通信。
  3. 同事类(Colleague): 同事类是相互交互的对象,它们通过中介者来通信而不是直接相互引用。
    中介者模式的主要优点包括:
  • 减少了对象之间的直接关联,使系统更加松耦合。
  • 提高了系统的可维护性,因为对象之间的通信逻辑集中在中介者中。
  • 可以更容易地扩展系统,添加新的同事类或更改现有的同事类。
    中介者模式通常在以下情况下使用:
  • 当系统中的对象之间存在复杂的相互关系,导致对象之间相互依赖性较高时,中介者模式可以帮助降低依赖性,提高系统的可维护性。
  • 当需要一个对象集中控制其他对象之间的通信时,中介者模式可以用来管理和协调对象之间的交互。

总之,中介者模式有助于将系统中的对象解耦,提高系统的灵活性和可维护性。它在复杂的系统中特别有用,可以帮助管理对象之间的复杂交互。

2. 使用的场景

中介者模式的使用场景通常包括以下情况:

  1. 对象之间的关系复杂: 当系统中的对象之间存在复杂的相互关系,导致对象之间相互依赖性较高时,中介者模式可以帮助降低依赖性,提高系统的可维护性。这种情况下,中介者充当了对象之间的协调者,负责管理它们之间的通信。
  2. 减少子类化: 在某些情况下,为了实现对象之间的通信,可能需要创建大量的子类。使用中介者模式可以减少子类化,因为对象通过中介者而不是直接相互引用。
  3. 分布式系统: 在分布式系统中,不同的组件通常需要进行通信,但直接通信可能会导致复杂性增加。中介者模式可以用于集中管理分布式系统中的通信。
  4. 图形用户界面(GUI)应用程序: GUI 应用程序中的用户界面元素通常需要相互响应用户操作。中介者模式可以用于管理用户界面元素之间的交互,以确保用户界面的一致性和协调性。
  5. 多人协作系统: 在多人协作系统中,不同用户可能需要共享信息或协同工作。中介者模式可以用于管理用户之间的通信和协作,以确保数据的一致性和安全性。
  6. 电子设备控制系统: 在家庭自动化或工业控制系统中,多个电子设备可能需要协同工作。中介者模式可以用于控制和协调这些设备之间的通信和操作。

总之,中介者模式适用于任何需要管理对象之间复杂关系和通信的场景,以提高系统的可维护性和灵活性。它有助于降低对象之间的耦合度,使系统更易于扩展和维护。

3. 应用例子

下面是一个使用 Python 实现的简单中介者模式示例,模拟了一个简单的聊天室应用程序,其中多个用户通过中介者进行聊天:

# 中介者接口
class Mediator:
    def send_message(self, message, user):
        pass

# 具体中介者
class ChatMediator(Mediator):
    def __init__(self):
        self.users = []

    def add_user(self, user):
        self.users.append(user)

    def send_message(self, message, user):
        for u in self.users:
            if u != user:
                u.receive_message(message)

# 同事类
class User:
    def __init__(self, name, mediator):
        self.name = name
        self.mediator = mediator

    def send(self, message):
        print(f"{self.name} 发送消息: {message}")
        self.mediator.send_message(message, self)

    def receive_message(self, message):
        print(f"{self.name} 收到消息: {message}")

# 使用示例
if __name__ == "__main__":
    chat_mediator = ChatMediator()

    user1 = User("User1", chat_mediator)
    user2 = User("User2", chat_mediator)
    user3 = User("User3", chat_mediator)

    chat_mediator.add_user(user1)
    chat_mediator.add_user(user2)
    chat_mediator.add_user(user3)

    user1.send("大家好!")
    user2.send("你好,User1!")
    user3.send("欢迎加入聊天!")

在这个示例中:

  • Mediator 是中介者接口,定义了 send_message 方法,用于发送消息给其他用户。
  • ChatMediator 是具体中介者类,实现了中介者接口,负责维护用户列表并协调用户之间的通信。
  • User 是同事类,每个用户都有一个名称和一个中介者。它们可以通过中介者发送和接收消息。

通过中介者模式,用户对象不需要直接与其他用户通信,而是通过中介者来发送和接收消息,从而降低了对象之间的耦合度。这有助于添加新用户和扩展聊天室功能。

4. 实现要素

中介者模式的实现要素包括以下部分:

  1. 中介者(Mediator): 中介者是一个接口或抽象类,定义了对象之间通信的协议。它通常包括方法来注册、删除和通知各个同事对象。
  2. 具体中介者(Concrete Mediator): 具体中介者是实现中介者接口的具体类,它负责实际协调和管理对象之间的通信。它需要维护一个对所有同事对象的引用。
  3. 同事类(Colleague): 同事类是相互交互的对象,它们通过中介者来通信而不是直接相互引用。同事类通常包括方法来发送消息给中介者以及接收来自中介者的消息。
  4. 具体同事类(Concrete Colleague): 具体同事类是实现同事类接口的具体类,它们通过中介者与其他同事对象通信。具体同事类之间通常存在一些关联和相互依赖。

5. Java/golang/javascrip/C++ 等语言实现方式

5.1 Java实现

上述例子用Java语言实现示例如下:

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

// 中介者接口
interface Mediator {
    void sendMessage(String message, User user);
}

// 具体中介者
class ChatMediator implements Mediator {
    private List<User> users = new ArrayList<>();

    @Override
    public void sendMessage(String message, User user) {
        for (User u : users) {
            if (u != user) {
                u.receiveMessage(message);
            }
        }
    }

    public void addUser(User user) {
        users.add(user);
    }
}

// 同事类
class User {
    private String name;
    private Mediator mediator;

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

    public void sendMessage(String message) {
        System.out.println(name + " 发送消息: " + message);
        mediator.sendMessage(message, this);
    }

    public void receiveMessage(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        ChatMediator chatMediator = new ChatMediator();

        User user1 = new User("User1", chatMediator);
        User user2 = new User("User2", chatMediator);
        User user3 = new User("User3", chatMediator);

        chatMediator.addUser(user1);
        chatMediator.addUser(user2);
        chatMediator.addUser(user3);

        user1.sendMessage("大家好!");
        user2.sendMessage("你好,User1!");
        user3.sendMessage("欢迎加入聊天!");
    }
}

在这个示例中:

  • Mediator 是中介者接口,定义了 sendMessage 方法,用于发送消息给其他用户。
  • ChatMediator 是具体中介者类,实现了中介者接口,负责维护用户列表并协调用户之间的通信。
  • User 是同事类,每个用户都有一个名称和一个中介者。它们可以通过中介者发送和接收消息。

通过中介者模式,用户对象不需要直接与其他用户通信,而是通过中介者来发送和接收消息,从而降低了对象之间的耦合度。这有助于添加新用户和扩展聊天室功能。

5.2 Golang实现

上述例子用golang实现示例如下:

package main

import (
        "fmt"
        "sync"
)

// Mediator 接口定义中介者的方法
type Mediator interface {
        SendMessage(message string, user *User)
}

// ChatMediator 是具体中介者类
type ChatMediator struct {
        users []*User
        mutex sync.Mutex
}

// NewChatMediator 创建 ChatMediator 实例
func NewChatMediator() *ChatMediator {
        return &ChatMediator{
                users: make([]*User, 0),
        }
}

// AddUser 将用户添加到中介者中
func (m *ChatMediator) AddUser(user *User) {
        m.mutex.Lock()
        defer m.mutex.Unlock()
        m.users = append(m.users, user)
}

// SendMessage 将消息广播给所有用户,除了发送者
func (m *ChatMediator) SendMessage(message string, sender *User) {
        m.mutex.Lock()
        defer m.mutex.Unlock()
        for _, user := range m.users {
                if user != sender {
                        user.ReceiveMessage(message)
                }
        }
}

// User 是同事类
type User struct {
        name     string
        mediator Mediator
}

// NewUser 创建 User 实例
func NewUser(name string, mediator Mediator) *User {
        return &User{
                name:     name,
                mediator: mediator,
        }
}

// SendMessage 发送消息
func (u *User) SendMessage(message string) {
        fmt.Printf("%s 发送消息: %s\n", u.name, message)
        u.mediator.SendMessage(message, u)
}

// ReceiveMessage 接收消息
func (u *User) ReceiveMessage(message string) {
        fmt.Printf("%s 收到消息: %s\n", u.name, message)
}

func main() {
        mediator := NewChatMediator()

        user1 := NewUser("User1", mediator)
        user2 := NewUser("User2", mediator)
        user3 := NewUser("User3", mediator)

        mediator.AddUser(user1)
        mediator.AddUser(user2)
        mediator.AddUser(user3)

        user1.SendMessage("大家好!")
        user2.SendMessage("你好,User1!")
        user3.SendMessage("欢迎加入聊天!")
}

在这个示例中:

  • Mediator 是中介者接口,定义了 SendMessage 方法,用于发送消息给其他用户。
  • ChatMediator 是具体中介者类,负责维护用户列表并协调用户之间的通信。
  • User 是同事类,每个用户都有一个名称和一个中介者。它们可以通过中介者发送和接收消息。

通过中介者模式,用户对象不需要直接与其他用户通信,而是通过中介者来发送和接收消息,从而降低了对象之间的耦合度。这有助于添加新用户和扩展聊天室功能。

5.3 Javascript实现

上述例子用javascript实现示例如下:

// 中介者接口
class Mediator {
  constructor() {
    this.users = [];
  }

  addUser(user) {
    this.users.push(user);
  }

  sendMessage(message, sender) {
    for (const user of this.users) {
      if (user !== sender) {
        user.receiveMessage(message);
      }
    }
  }
}

// 具体中介者
class ChatMediator extends Mediator {
  constructor() {
    super();
  }
}

// 同事类
class User {
  constructor(name, mediator) {
    this.name = name;
    this.mediator = mediator;
  }

  sendMessage(message) {
    console.log(`${this.name} 发送消息: ${message}`);
    this.mediator.sendMessage(message, this);
  }

  receiveMessage(message) {
    console.log(`${this.name} 收到消息: ${message}`);
  }
}

// 使用示例
const chatMediator = new ChatMediator();

const user1 = new User("User1", chatMediator);
const user2 = new User("User2", chatMediator);
const user3 = new User("User3", chatMediator);

chatMediator.addUser(user1);
chatMediator.addUser(user2);
chatMediator.addUser(user3);

user1.sendMessage("大家好!");
user2.sendMessage("你好,User1!");
user3.sendMessage("欢迎加入聊天!");

在这个示例中:

  • Mediator 是中介者类,负责维护用户列表并定义 addUser 和 sendMessage 方法。
  • ChatMediator 是具体中介者类,继承自 Mediator,用于实际协调用户之间的通信。
  • User 是同事类,每个用户都有一个名称和一个中介者。它们可以通过中介者发送和接收消息。

通过中介者模式,用户对象不需要直接与其他用户通信,而是通过中介者来发送和接收消息,从而降低了对象之间的耦合度。这有助于添加新用户和扩展聊天室功能。

5.4 C++实现

上述例子用C++实现如下:

#include <iostream>
#include <vector>

// 前向声明
class User;

// 中介者抽象类
class Mediator {
public:
    virtual void addUser(User* user) = 0;
    virtual void sendMessage(const std::string& message, User* sender) = 0;
};

// 具体中介者类
class ChatMediator : public Mediator {
private:
    std::vector<User*> users;

public:
    void addUser(User* user) override {
        users.push_back(user);
    }

    void sendMessage(const std::string& message, User* sender) override {
        for (User* user : users) {
            if (user != sender) {
                user->receiveMessage(message);
            }
        }
    }
};

// 用户类
class User {
private:
    std::string name;
    Mediator* mediator;

public:
    User(const std::string& name, Mediator* mediator) : name(name), mediator(mediator) {
        mediator->addUser(this);
    }

    void sendMessage(const std::string& message) {
        std::cout << name << " 发送消息: " << message << std::endl;
        mediator->sendMessage(message, this);
    }

    void receiveMessage(const std::string& message) {
        std::cout << name << " 收到消息: " << message << std::endl;
    }
};

int main() {
    ChatMediator chatMediator;

    User user1("User1", &chatMediator);
    User user2("User2", &chatMediator);
    User user3("User3", &chatMediator);

    user1.sendMessage("大家好!");
    user2.sendMessage("你好,User1!");
    user3.sendMessage("欢迎加入聊天!");

    return 0;
}

在这个示例中:

  • Mediator 是中介者抽象类,定义了 addUser 和 sendMessage 纯虚函数。
  • ChatMediator 是具体中介者类,继承自 Mediator,负责维护用户列表并协调用户之间的通信。
  • User 是用户类,每个用户都有一个名称和一个中介者指针。它们可以通过中介者发送和接收消息。

通过中介者模式,用户对象不需要直接与其他用户通信,而是通过中介者来发送和接收消息,从而降低了对象之间的耦合度。这有助于添加新用户和扩展聊天室功能。

7. 练习题

假设你正在开发一个多人游戏,其中有多个玩家角色。这些角色可以相互交互,比如发送消息、交换物品等。使用中介者模式设计一个游戏中的聊天系统,其中玩家角色可以通过中介者发送和接收消息。

要求:

  1. 创建一个中介者类,用于协调玩家角色之间的通信。
  2. 创建多个玩家角色类,它们可以向中介者发送消息,并能够接收来自其他玩家的消息。
  3. 模拟玩家之间的交互,例如,一个玩家发送消息后,其他玩家能够收到该消息并显示在控制台上。
  4. 编写一个示例程序来演示中介者模式在多人游戏中的应用。

你可以使用 C++、Java、Python 或任何其他编程语言来实现这个练习。
你可以在评论区里或者私信我回复您的答案,这样我或者大家都能帮你解答,期待着你的回复~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guohuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值