Java设计模式之中介者模式

1. 中介者模式

1.1 定义、优缺点、适用场景

定义:中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式属于行为型模式

优点

  • 各个客户只需和中介进行交互,将网状结构分离为星型结构,进行了解耦。符合迪米特原则
  • 可以很方便的增加新的客户类,维护性和拓展性好

缺点:中介者承担了较多的责任,变得过于复杂,一旦中介者出现了问题,整个系统就会受到影响

适用场景

  • MVC模式,C(Controller控制器)是M(Model模型)和V(View视图)的中介者,在前后端交互时起到了中间人的作用
  • 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解时,就可以用中介者模式解决
  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象时,就可以用中介者模式解决
  • 需要通过一个中间类来封装多个类中的行为,但又不想生成太多的子类

1.2 模式的结构与实现

结构

  • 抽象客户类(Customer):定义客户类的抽象类,保存中介者对象,实现客户类的公共方法
  • 具体客户类(ConcreteCustomer):实现抽象客户类。每个客户只知道自己的行为,而不了解其它客户类的行为,需要通过中介者间接完成具体客户类之间的通信交互
  • 抽象中介者(Mediator):定义了客户对象到中介者对象的接口
  • 中介者对象(ConcreteMediator):实现抽象方法, 他需要知道所有的具体的客户类, 即以一个HashMap来管理。并接收某个客户的消息,完成相应的任务

实现
智能家居项目:早上闹钟响起的时候,窗帘自动打开;之后我们开灯,闹钟自动关闭。所有的家电控制都经中央处理系统进行控制,而不是家电之间相互控制

import java.util.HashMap;


public class MediatorTest {

    public static void main(String[] args) {

        // 创建一个中介者对象
        Mediator mediator = new CentralMediator();

        // 创建各个Customer对象并且加入到CentralMediator对象的HashMap中
        Alarm alarm = new Alarm(mediator, "alarm");
        Curtain curtain = new Curtain(mediator, "curtain");
        Lamp lamp = new Lamp(mediator, "lamp");

        // 闹钟响了,会自动打开窗帘
        alarm.openAlarm();
        // 灯开了,会自动关闭闹钟
        lamp.openLamp();
    }

}


// 抽象客户类
abstract class Customer {
    protected Mediator mediator;
    protected String name;

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

    // 客户向中介发送消息,中介根据客户的消息做处理
    public abstract void sendMessage(String message);
}


// 具体的客户类-闹钟
class Alarm extends Customer {

    public Alarm(Mediator mediator, String name) {
        super(mediator, name);

        // 创建Alarm对象时,将自身注册到中央处理系统的HashMap中
        this.mediator.Register(this.name, this);
    }

    @Override
    public void sendMessage(String message) {
        // 发送的消息,由中央处理系统进行接收并处理
        this.mediator.getMessage(this.name, message);
    }

    public void openAlarm() {
        System.out.println("闹钟响了,开始向中央处理系统发送开启窗帘的消息");
        this.sendMessage("开启窗帘");
    }

    public void closeAlarm() {
        System.out.println("闹钟已关闭");
    }

}


// 具体的客户类-窗帘
class Curtain extends Customer {

    public Curtain(Mediator mediator, String name) {
        super(mediator, name);

        // 创建Curtain对象时,将自身注册到中央处理系统的HashMap中
        this.mediator.Register(this.name, this);
    }

    @Override
    public void sendMessage(String message) {
        // 窗帘不控制其它家电,不用实现该方法
    }

    public void openCurtain() {
        System.out.println("窗帘已打开");
    }

}


// 具体的客户类-灯
class Lamp extends Customer {

    public Lamp(Mediator mediator, String name) {
        super(mediator, name);

        // 创建Lamp对象时,将自身注册到中央处理系统的HashMap中
        this.mediator.Register(this.name, this);
    }

    @Override
    public void sendMessage(String message) {
        // 发送的消息,由中央处理系统进行接收并处理
        this.mediator.getMessage(this.name, message);
    }

    public void openLamp() {
        System.out.println("灯已打开,开始向中央处理系统发送关闭闹钟的消息");
        this.sendMessage("关闭闹钟");
    }

}

// 抽象中介者
abstract class Mediator {
    // 将中介者的客户注册到HashMap中
    public abstract void Register(String customerName, Customer customer);

    // 接收客户的消息, 并根据消息和其它客户交互
    public abstract void getMessage(String customerName, String message);

}


// 具体的中介者-中央处理系统
class CentralMediator extends Mediator {
    // 保存所有的家电对象
    private HashMap<String, Customer> customerMap;
    // 保存所有的电器种类名称和电器名称
    private HashMap<String, String> nameMap;

    public CentralMediator() {
        this.customerMap = new HashMap<String, Customer>();
        this.nameMap = new HashMap<String, String>();
    }

    @Override
    public void Register(String customerName, Customer customer) {
        this.customerMap.put(customerName, customer);

        if (customer instanceof Alarm) {
            this.nameMap.put("Alarm", customerName);
        } else if (customer instanceof Curtain) {
            this.nameMap.put("Curtain", customerName);
        } else if (customer instanceof Lamp) {
            this.nameMap.put("Lamp", customerName);
        }
    }

    // 接收家电发送的消息,并做出相应的处理
    @Override
    public void getMessage(String customerName, String message) {
        // 处理闹钟发出的消息
        if (this.customerMap.get(customerName) instanceof Alarm) {
            if (message == "开启窗帘") {
                // 调用窗帘,进行窗帘的打开
                ((Curtain) this.customerMap.get(this.nameMap.get("Curtain"))).openCurtain();
            }
        } else if (this.customerMap.get(customerName) instanceof Lamp) {
            if (message == "关闭闹钟") {
                // 调用闹钟,进行闹钟的关闭
                ((Alarm) this.customerMap.get(this.nameMap.get("Alarm"))).closeAlarm();
            }
        }

    }

}

运行程序,结果如下:

闹钟响了,开始向中央处理系统发送开启窗帘的消息
窗帘已打开
灯已打开,开始向中央处理系统发送关闭闹钟的消息
闹钟已关闭
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值