智能家庭
智能家居有许多。当你起床时,你希望各个设备能够协同做一些事情。
比如:闹钟响起->音响播放音乐->空调关闭
传统方案:
问题:
当有多种电器时,相互之间的调用关系会比较复杂。不利于松耦合。
各个对象之间传递的内容容易混乱
当系统中途增加一个电器对象,或者执行流程改变,则需要改动代码较大,不利于系统的可维护性、扩展性。
中介者模式
用一个中介对象来封装一系列的对象交互。则中介者可以使各个对象不需要显示地相互引用,从而松耦合,又可以独立地改变它们之间的交互。
中介者模式结构
1.组件 (Component)
是含有各种业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。组件不知中介者实际所属的类, 则可通过连接不同的中介者,提高复用。
2.中介者 (Mediator)
接口声明了与组件交流的方法(通常只有一个通知方法)。组件可将任意上下文(Context)作为通知方法的参数, 使接收组件与发送者不耦合。
3.具体中介者 (Concrete Mediator)
封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。
组件并不知道其他组件的情况。 如果组件内发生了重要事件, 它只能通知中介者。 中介者收到通知后能轻易地确定发送者, 这或许已足以判断接下来需要触发的组件了。对于组件来说, 中介者看上去完全就是一个黑箱。 发送者不知道最终会由谁来处理自己的请求, 接收者也不知道最初是谁发出了请求。
中介者模式适合应用场景
1.当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。
2.当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。
3.如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式。
实现方式
- 找到一组当前紧密耦合, 且提供其独立性能带来更大好处的类 (例如更易于维护或更方便复用)。
- 声明中介者接口并描述中介者和各种组件之间所需的交流接口。 在绝大多数情况下, 一个接收组件通知的方法就足够了。 如果你希望在不同情景下复用组件类, 那么该接口将非常重要。 只要组件使用通用接口与其中介者合作, 你就能将该组件与不同实现中的中介者进行连接。
- 实现具体中介者类。 该类可从自行保存其下所有组件的引用中受益。
- 你可以更进一步, 让中介者负责组件对象的创建和销毁。 此后, 中介者可能会与工厂或外观类似。
- 组件必须保存对于中介者对象的引用。 该连接通常在组件的构造函数中建立, 该函数会将中介者对象作为参数传递。
- 修改组件代码, 使其可调用中介者的通知方法, 而非其他组件的方法。 然后将调用其他组件的代码抽取到中介者类中, 并在中介者接收到该组件通知时执行这些代码。
中介者模式优缺点
优点:
✔️ 单一职责原则。 你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
✔️ 开闭原则。 你无需修改实际组件就能增加新的中介者。
✔️ 你可以减轻应用中多个组件间的耦合情况。
✔️ 你可以更方便地复用各个组件。
缺点:
❌一段时间后, 中介者可能会演化成为上帝对象。
解决智能家庭
代码:
//同事抽象类
public 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 mediator;
}
public abstract void sendMessage(int stateChange);
}
public class Clock extends Colleague{
public Clock(Mediator mediator,String name) {
super(mediator,name);
mediator.register(name,this);
}
@Override
public void sendMessage(int stateChange) {
this.getMediator().getMessage(stateChange,this.name);
}
public void colockOpen(){
System.out.println("闹钟响了");
}
public void colockStop(){
System.out.println("闹钟停了");
}
public void sendColock(int stateChange){
colockOpen();
sendMessage(stateChange);
}
}
public class Sound extends Colleague{
public Sound(Mediator mediator,String name) {
super(mediator,name);
mediator.register(name,this);
}
@Override
public void sendMessage(int stateChange) {
this.getMediator().getMessage(stateChange,this.name);
}
public void soundOpen(){
System.out.println("音响打开");
}
public void soundStop(){
System.out.println("音响关闭");
}
public void soundPlaying(){
System.out.println("音响播放...");
}
public void sendSound(int stateChange){
sendMessage(stateChange);
}
}
public class AirCondition extends Colleague{
public AirCondition(Mediator mediator,String name) {
super(mediator,name);
mediator.register(name,this);
}
@Override
public void sendMessage(int stateChange) {
this.getMediator().getMessage(stateChange,this.name);
}
public void airConditionOpen(){
System.out.println("打开空调");
}
public void airConditionStop(){
System.out.println("关闭空调");
}
}
public abstract class Mediator {
//给中介者对象,加入到集合中
public abstract void register(String colleagueName,Colleague colleague);
//接收消息,由具体的同时对象发出
public abstract void getMessage(int stateChange,String colleagueName);
public abstract void SendMessage();
}
//具体的中介者类
public class ConcreteMediator extends Mediator {
//集合,存入所有的同时对象
private HashMap<String,Colleague> colleagueHashMap;
private HashMap<String,String> interMap;
public ConcreteMediator() {
colleagueHashMap = new HashMap<>();
interMap = new HashMap<>();
}
@Override
public void register(String colleagueName, Colleague colleague) {
colleagueHashMap.put(colleagueName,colleague);
if (colleague instanceof Clock){
interMap.put("Clock",colleagueName);
}else if (colleague instanceof AirCondition){
interMap.put("AirCondition",colleagueName);
}else if(colleague instanceof Sound){
interMap.put("Sound",colleagueName);
}
}
/*
核心方法
1.得到消息后,完成对应任务
2.中介者在这里协调各个具体的同事对象
*/
@Override
public void getMessage(int stateChange, String colleagueName) {
//处理闹钟的消息
if (colleagueHashMap.get(colleagueName) instanceof Clock){
if (stateChange == 0){
((Sound)(colleagueHashMap.get(interMap.get("Sound")))).soundOpen();
}
if (stateChange == 1){
((Sound)(colleagueHashMap.get(interMap.get("Sound")))).soundPlaying();
}
}else if (colleagueHashMap.get(colleagueName) instanceof Sound){ //处理音响的信息
((AirCondition)colleagueHashMap.get(interMap.get("AirCondition"))).airConditionStop();
}else if (colleagueHashMap.get(colleagueName) instanceof AirCondition){
System.out.println("流程完毕...");
}
}
@Override
public void SendMessage() {
}
}
public class Client {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
Clock clock = new Clock(mediator,"clock");
Sound sound = new Sound(mediator,"sound");
AirCondition airCondition = new AirCondition(mediator,"airCondition");
clock.sendColock(1);
sound.sendSound(0);
}
}
中介者模式的注意事项和细节
1.多个类相互耦合,会形成网状结构 , 使用中介者模式将网状结构分离为星型结构
进行解耦
2.减少类间依赖,降低了耦合符合迪米特原则
3.中介者承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响
4.如果设计不当,中介者对象本身变得过于复杂, 这点在实际使用时,要特别注意