1、智能家庭管理问题
智能家庭项目:
1)智能家庭包括各种设备,闹钟、咖啡机、电视机、窗帘等
2)主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,
-
比如流程为:闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放
-
当各电器对象有多种状态改变时,相互之间的调用关系会比较复杂
-
各个电器对象彼此联系,你中有我,我中有你,不利于松耦合.
-
各个电器对象之间所传递的消息(参数),容易混乱
-
当系统增加一个新的电器对象时,或者执行流程改变时,代码的可维护性、扩展性都不理想
- →考虑中介者模式
2、基本介绍
-
中介者模式(Mediator Pattern),用一中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而便其耦合松散,而且可以独立地改变它们之间的交互
-
中介者模式属于行为型模式,使代码易于维护
-
比如
MVC
模式,-
c
(Controller
控制器)是M
(Model
模型)和v
(View
视图)的中介者, -
controller
就是封装了model
和view
,返回一个ModelAndWiew
对象 -
在前后端交互时起到了中间人的作用
-
就是
controller
对应的适配器(adapter
)去执行相应的controller
,- 其中执行
controller
里面就用到了中介者模式,
- 其中执行
-
然后返回一个
ModelAndWiew
对象
-
-
实例中,多个用户可以向聊天室发送消息,聊天室向所有的用户显示消息。
3、原理类图
1:Mediator
,
- 抽象的中介者,定义了同事对象到中介者对象的接口
2:Colleage
,
- 抽象同事类
3:ConcreteMediator
,
- 具体的中介者对象,实现抽象方法,他需要知道所有的具体的同事类,即以一个集合来管理,并接受某个同事对象的消息,完成相应的任务
- 类似于注册中心
4:ConcreteColleage
,
- 具体的同事类,很多,只知道自己的行为,而不了解其他同事类的行为(方法),
但是他们都依赖中介者对象(通过中介者进行同事间的联系)
4、案例解决
1: 创建ConcreteMediator
对象
2: 创建各个同事类对象, Alarm
、CoffeeMachine
、TV
3:创建同事类对象的时候,就直接通过构造器注入到colleageMap
4:同事类对象,可以调用sendMessage
,最终会去调用ConcreteMediator
的getMessage
方法
5:getMessag
会根据接受到的同事对象发出的消息来协调调用其他的同事对象完成相应任务
6:可以看到getMessage
是核心方法,完成相应的任务
public class Client {
public static void main(String[] args) {
//创建一个中介者对象
Mediator mediator = new ConcreteMediator();
//创建alarm 并且注册到 ConcreteMediator,对象的HashMap
Alarm alarm = new Alarm(mediator,"alarm");
alarm.sendMessage(0);
alarm.sendMessage(1);
}
}
/**
* 中介者抽象类
*/
public abstract class Mediator {
/**
* 集合,放入所有的同事对象
*/
protected Map<String, Colleague> colleagueMap;
public Mediator() {
colleagueMap = new HashMap<>();
}
/**
* 将中介者对象,加入到集合中
*/
public void register(String name, Alarm alarm) {
colleagueMap.put(name, alarm);
}
/**
* 中介者的核心方法
* 1. 根据得到消息,完成对应任务
* 2. 中介者在这个方法,协调各个同事的具体对象,完成任务
* 接受消息,具体的同事对象发出
*
* @param stateChange 状态调用
* @param name 同事名称
*/
public abstract void getMessage(int stateChange, String name);
}
/**
* 具体的中介者
*/
public class ConcreteMediator extends Mediator {
@Override
public void getMessage(int stateChange, String name) {
Colleague colleague = colleagueMap.get(name);
String simpleName = colleague.getClass().getSimpleName();
switch (simpleName) {
case "Alarm":
Alarm alarm = (Alarm) colleague;
if (stateChange == 0){
alarm.startAlarm();
}else if (stateChange == 1){
alarm.endAlarm();
}
break;
//....
default:
}
}
}
/**
* 同事抽象类
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class Colleague {
private Mediator mediator;
private String name;
/**
* 发送消息
* @param stateChange 改变的状态
*/
public abstract void sendMessage(int stateChange);
}
/**
* 具体的同事类
*/
public class Alarm extends Colleague {
public Alarm() {
}
public Alarm(Mediator mediator, String name) {
super(mediator, name);
//在创建同事对象的时候,将自己注册到ConcreteMediator 对象中[集合]
mediator.register(name,this);
}
@Override
public void sendMessage(int stateChange) {
//调用中介者对象的getMessage
getMediator().getMessage(stateChange,this.getName());
}
public void startAlarm(){
System.out.println("开始alarm");
}
public void endAlarm(){
System.out.println("结束alarm");
}
}
5、注意事项与细节
-
多个类相互耦合,会形成网状结构,使用中介者模式将网状结构分离为星型结构,进行解耦
-
减少类间依赖,降低了耦合,符合迪米特原则
-
中介者承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响
-
如果设计不当,中介者对象本身变得过于复杂,这点在实际使用时,要特别注意
6、中介者模式-springMVC
-
c
(Controller
控制器)是M
(Model
模型)和v
(View
视图)的中介者, -
controller
就是封装了model
和view
,返回一个ModelAndWiew
对象 -
在前后端交互时起到了中间人的作用
-
就是
controller
对应的适配器(adapter
)去执行相应的controller
,- 其中执行
controller
里面就用到了中介者模式,
- 其中执行
-
然后返回一个
ModelAndWiew
对象
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("loginRecords")
public ModelAndView getLoginRecords(ModelAndView mav){
Model model = userService.getCurrentUserLoginRecords(); //获取登录记录的数据模型
mav.addObject("model", model);
mav.setViewName("record.jsp");//返回到 jsp,在 jsp 中使用 model 数据渲染页面
return mav;
}