中介者模式

中介者模式 Mediator 概述

什么是中介者
中介者又被称为调停者,调节者,协调者举例说明: 例如QQ发送消息给对方,例如发送短信,我们是将消息发送给QQ这个平台,通过这个平台找到接收者,这个平台就相当于中介角色协调者角色,发送消息与接收消息的双方被称为"同事",又被称为被协调者,例如当接收到某个消息时,协调者进行协调,然后进行其他的处理等,而中介者中进行逻辑处理的方法被称为协调方法
中介者模式的优点
中介者模式是行为型设计模式, 在项目功能架构时,添加中介者对象,通过中介者来控制一系列对象之间的交互,减少各个对象之间显示的相互引用,从而降低耦合,并且可以在中介者中定制他们的交互行为,降低多个对象间通信的复杂性
中介者模式角色分析

  • 抽象中介者 Mediator : 提供将同事对象存入中介者容器中的接口,与接收同事对象发送的消息接口也叫做协调方法
  • 具体中介者 ConcreteMediator : 持有所有需要通信的同事对象容器,实现向容器中存放通信对象的方法,与接收同事消息的方法,接收到消息后,根据需求,将消息发送给容器中的指定接收同事对象,或者中介者接收到消息后,进行指定的逻辑处理等
  • 抽象同事 Colleague : 持有中介者对象,当同事对象发送消息时,实际是通过持有的中介者对象,调用中介者方法,将消息发送给了中介者,所有通信同事都需要存放在中介者的容器中,所以提供构造器,在调用构造器进行初始化同事对象时,就将当前同事对象this,通过持有的中介者,调用方法,存入容器中
  • 具体同事 ConcreteColleague : 继承抽象同事,重写发送消息方法,当发送消息时根据需求编写具体的逻辑代码,重点是通过持有的中介者,将消息发送给中介者,通过中介者对消息进行处理

示例

案例: 通过闹铃定时,某个时刻闹铃发送发送消息,咖啡机煮咖啡,打开电视,播放电视,当闹铃响再次响起时发送消息,关闭电视…

  1. 创建抽象中介者 receptionMessage() 方法就是协调方法
interface Mediator {
    //将通信同事对象,加入到中介者用来存放通信同事的容器集合中
    public void register(Colleague colleague);

    //接收同事发送的消息,根据需求在该方法中编写逻辑代码,
    //将消息发送给指定的接收同事,做到转发与调解的作用
    public void receptionMessage(int stateChange, Colleague colleague);
}
  1. 创建具体中介者,具体中介者中持有所有同事容器,并实现接收到同事消息后怎么处理消息的协调方法方法receptionMessage()
//具体的中介者
class ConcreteMediator implements Mediator {
    //存放了发送消息,与接收消息的同事
    private HashMap<String, Colleague> colleagueMap;

    public ConcreteMediator() {
        colleagueMap = new HashMap<>();
    }

    @Override
    public void register(Colleague colleague) {
        colleagueMap.put(colleague.name, colleague);

    }

    @Override
    public void receptionMessage(int stateChange, Colleague colleague) {
        //1.获取容器中的同事
        Object obj = colleagueMap.get(colleague.name);
        //当是闹铃时判断消息,如果消息是"0" 开始煮咖啡
        //播放电视,当消息是"1"时,停止播放电视
        if (obj instanceof Alarm) {
            if (stateChange == 0) {
                ((CoffeeMachine) (colleagueMap.get("CoffeeMachine"))).startCoffee();
                ((TV) (colleagueMap.get("TV"))).startTV();
            } else if (stateChange == 1) {
                ((TV) (colleagueMap.get("TV"))).stopTV();
            }
            //2.当在容器中获取的同事是咖啡机时,升起窗帘
        } else if (colleagueMap.get(colleague.name) instanceof CoffeeMachine) {
            ((Curtains) (colleagueMap.get("Curtains"))).upCurtains();
        } else if (colleagueMap.get(colleague.name) instanceof TV) {

        } else if (colleagueMap.get(colleague.name) instanceof Curtains) {

        }
    }
}
  1. 创建抽象同事,抽象同事持有中介者对象,
abstract class Colleague {
    public Mediator mediator;
    public String name;

    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }
    //返回持有的中介者
    public Mediator getMediator() {
        return this.mediator;
    }
    //发送消息的抽象方法(根据需求在子类中实现,重点:在中介者模式中
    //是将消息发送给了中介者,通过中介者将消息发送给指定的接收者)
    public abstract void sendMessage(int stateChange);
}
  1. 创建具体同事: 具体同事可能存在多个,通信双方等,所有同事对象初始化后都要放在中介者的容器中,根据需求实现发送消息方法,但是最终是将主要消息通过持有的中介者对象,将消息发送给了中介者,通过中介者进行调解处理
    具体同事"闹铃"
class Alarm extends Colleague {

    public Alarm(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register(this);
    }

    public void sendAlarm(int stateChange) {
        System.out.println("闹了响起,到点了");
        sendMessage(stateChange);
    }

    //闹铃发送消息实现,实际是通过持有的中介者对象,
    //调用中介者的receptionMessage()方法,通过中介者
    //进行指定处理:例如中介者接收到这个消息以后,
    //进行其他操作,再例如中介者接收到消息以后,通过
    //中介者,获取容器中的同事对象,将消息进行转发
    @Override
    public void sendMessage(int stateChange) {
        //调用中介者对象的receptionMessage()方法
        this.getMediator().receptionMessage(stateChange, this);
    }
}

咖啡机

class CoffeeMachine extends Colleague {

    public CoffeeMachine(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register(this);
    }

    public void sendAlarm(int stateChange) {
        sendMessage(stateChange);
    }

    @Override
    public void sendMessage(int stateChange) {
        this.getMediator().receptionMessage(stateChange, this);
    }

    public void startCoffee() {
        System.out.println("咖啡机开始煮咖啡");
    }
    public void finishCoffee(){
        System.out.println("咖啡煮好了");
        sendMessage(0);
    }
}

电视

//具体同事类"TV"
class TV extends Colleague {

    public TV(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register( this);
    }

    public void sendAlarm(int stateChange) {
        sendMessage(stateChange);
    }

    @Override
    public void sendMessage(int stateChange) {
        this.getMediator().receptionMessage(stateChange, this);
    }

    public void startTV() {
        System.out.println("打开电视,开始播放");
    }
    public void stopTV(){
        System.out.println("关闭电视,停止播放");
    }
}

窗帘

class Curtains extends Colleague {

    public Curtains(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register(this);
    }

    public void sendAlarm(int stateChange) {
        sendMessage(stateChange);
    }

    @Override
    public void sendMessage(int stateChange) {
        this.getMediator().receptionMessage(stateChange, this);
    }

    public void upCurtains() {
        System.out.println("打开窗帘");
    }
}
  1. 调用测试
	public static void main(String[] args) {
        //创建中介者对象
        Mediator mediator = new ConcreteMediator();
        //通信时需要双方都存在,然后通过中介者,进行协调调用
        //所以首先要将需要通信的对象初始化,放入中介者容器中
        //创建Alarm闹钟具体同事对象
        Alarm alarm = new Alarm(mediator, "Alarm");
        //创建CoffeeMachine咖啡机具体同事对象
        CoffeeMachine coffeeMachine = new CoffeeMachine(mediator, "CoffeeMachine");
        //创建窗帘具体同事对象
        Curtains curtains = new Curtains(mediator, "Curtains");
        //创建电视具体同事对象
        TV tv = new TV(mediator, "TV");
        alarm.sendAlarm(0);
        //coffeeMachine.finishCoffee();

        alarm.sendAlarm(1);
    }

根据代码分析理解

我理解的是,所有发送接收消息的同事都持有同一个中介者,在初始化同事对象时,将这个同事对象本身this,通过持有的中介者对象,放入中介者容器中,这样所有的发送消息,的同事对象都存入了中介者容器中,当同事发送消息时,实际是通过持有的中介者对象,将消息发送给了中介者,中介者接收到消息后,在中介者中进行逻辑处理,例如接收到闹铃的消息"0"时煮咖啡,播放电视,接收到闹铃的消息"1"时关闭电视,接收到咖啡消息时窗帘上升,在例如将获取消息,将消息转发给容器中指定的其他同事等,这样所有的同事只与中介者打交道,减少同事与同事之间相互调用的复杂关系

JDK 中 中介者模式的使用案例

查看jdk中 java.util.Timer,计时器相关的类,该类可以看为是一个中介者,该类中的sched()方法可以看为是协调方法,方法中的 TimerTask 可以看为同事类,被协调者

业务与设计模式落地案例

  1. 通过中介者模式来实现用户之间的消息传递和沟通
  2. 定义中介者接口,包含向指定用户发送消息、向所有用户广播消息、添加用户、移除用户等方法
public interface ChatMediator {
    void sendMessage(User sender, User receiver, String message);
    void broadcastMessage(User sender, String message);
    void addUser(User user);
    void removeUser(User user);
}
  1. 定义具体的中介者实现类,该类维护了一个用户列表,管理所有的聊天用户,当用户发送消息或广播消息时,中介者将相应的消息传递给目标用户或所有用户
@AllArgsConstructor
public class ChatMediatorImpl implements ChatMediator {
    private final List<User> users;

    @Override
    public void sendMessage(User sender, User receiver, String message) {
        receiver.receiveMessage(sender, message);
    }

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

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

    @Override
    public void removeUser(User user) {
        users.remove(user);
    }
}
  1. 定义用户对象,包含用户ID、名称、中介者等属性
@Data
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private ChatMediator mediator;
	
	//发送消息
    public void sendMessage(User receiver, String message) {
        mediator.sendMessage(this, receiver, message);
    }

	//广播消息
    public void broadcastMessage(String message) {
        mediator.broadcastMessage(this, message);
    }

	//处理接收到的消息
    public void receiveMessage(User sender, String message) {
        System.out.println("[收到消息] " + sender.getName() + ": " + message);
    }
}
  1. Controller中实现用户聊天的业务逻辑
@RestController
@RequestMapping("/chat")
@AllArgsConstructor
public class ChatController {
    private final ChatMediator mediator;
	
	//向指定用户发送消息
    @PostMapping("/{senderId}/send")
    public String sendMessage(@PathVariable Long senderId, @RequestParam Long receiverId, @RequestParam String message) {
        User sender = getUserById(senderId);
        User receiver = getUserById(receiverId);

        sender.sendMessage(receiver, message);
        return "发送成功";
    }

	//向所有用户广播消息
    @PostMapping("/{senderId}/broadcast")
    public String broadcastMessage(@PathVariable Long senderId, @RequestParam String message) {
        User sender = getUserById(senderId);
        sender.broadcastMessage(message);
        return "发送成功";
    }

    private User getUserById(Long userId) {
        // 省略获取用户信息的代码
        return new User(userId, "User " + userId, mediator);
    }
}
  1. 通过这种方式,可以将用户之间的聊天行为完全解耦,所有的消息传递都通过ChatMediator对象进行,避免了直接耦合引起的系统复杂度过高的问题,还可以很方便地管理所有的聊天用户,并随时添加,删除或修改中介者对象和用户对象,不需要对现有代码进行修改
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值