mediator

第十九章 中介者模式(Mediator Pattern)

1 概要

中介者模式(Mediator Pattern)是一种行为模式(Behavior Design Patters)。中介者模式能够简化多个对象之间的相互交互,并且将对象内部逻辑与相互交互的逻辑分离开。因此,在中介者模式下,能够独立的改变对象之间交互的方式,而不影响对象内部的逻辑。

从下面的示意图中我们可以看到,假设一个系统中有四个对象Object 1, Object 2, Object 3和Object4。它们之间相互调用。更复杂的是,Object 1可能调用了Object 2的一个方法。在该方法返回之前,Object 2可能需要调用Object 3的方法。在Object 3的方法中,可能还需要调用Object 4的方法。这种逐层调用的场景会使得代码逻辑变得更为复杂,难以维护。

图一 中介者模式解决方案

图一 中介者模式解决方案。

因此,一个更合理的设计是使用中介者模式来帮助对象之间的调用(交互)。中介者是系统中的一个新的对象,它负责处理和传递对象之间的调用。因此,对于对象而言,它只可能被中介者对象调用。当该对象需要调用其他对象时,它只需要“通知”中介者对象即可。这样的设计极大的简化了对象内部逻辑,也将复杂的调用关系分离并实现在中介者对象中。

2 中介者模式的结构

在中介者模式中,有四个参与方。

  1. Subject接口定义了对象相互调用的接口。
  2. RealSubject类实现了Subject接口,并在实现的方法中,完成了真实的逻辑处理。
  3. Mediator接口定义了帮助Subject对象之间相互交互的接口。
  4. RealMediator类实现了Mediator接口,即:它实现了Subject对象相互交互的逻辑。

图二 中介者模式结构

图二 中介者模式结构。

3 中介者模式示例

我们使用一个简单的用例来展示中介者模式的用法。这个用例实现了一个简单的、同事之间更新状态的功能。这个用例定义了一个接口ColleagueItf。该接口声明了五个成员方法。其中,getName()返回该同事的姓名。getStatus()/setStatus()分别查询和更新自身的状态。syncStatus()/syncStatusToColleague()方法则向其他同事更新自身的状态。MediatorItf接口定义了中介者的职责。成员方法register()向中介者注册参与者。成员方法sync()/syncToAll()将发起者的状态发送给其他的参与者。

interface ColleagueItf {
    String getName();
    String getStatus();
	void setStatus(String status);
	void syncStatus();
    void syncStatusToColleague(String name);
}

interface MediatorItf {
    void register(ColleagueItf participant);
    void syncToAll(ColleagueItf sender);
    void sync(ColleagueItf sender, String name);
}

ColleagueImpl类实现了ColleagueItf接口。ColleagueImpl类定义了一个status成员变量,用于保存目前的状态。成员变量mediator则指向中介者,用于将自身状态同步给其他同事。

public class ColleagueImpl implements ColleagueItf {
    private String name = null;
    private String status = null;
	private MediatorItf mediator = null;
	public ColleagueImpl(MediatorItf mediator, String name) {
        this.name = name;
	    this.status = "Normal";
		this.mediator = mediator;
	}
    
    @Override
    public String getName() {
        return this.name;
    }
	
    @Override
	public String getStatus() {
	    return this.status;
	}
	
	@Override
	public void setStatus(String status) {
	    this.status = status;
	}
	
	@Override
	public void syncStatus() {
	    this.mediator.sync(this);
	}
    
    @Override
    void syncStatusToColleague(String name) {
        this.mediator.sync(this, name);
    }
}

MediatorImpl类实现了接口MediatorItf。MediatorImpl使用成员变量participants维护着所有的参与者。成员方法register()向该对象添加新的参与者,而成员方法sync()/syncToAll()将状态通知给其他参与者。

import java.util.List;
import java.util.LinkedList;

public class MediatorImpl implements MediatorItf {
    List<ColleagueItf> participants = new LinkedList<ColleagueItf>();
	
	@Override
    public void register(ColleagueItf participant) {
	    participants.add(participant);
	}
	
	@Override
    public void syncToAll(ColleagueItf sender) {
	    String status = sender.getStatus();
		for (ColleagueItf oneParticipant: participants) {
		    if (oneParticipant != sender)
			    sender.updateStatus(status);
		}
	}
    
    @Override
    public void sync(ColleagueItf sender, String name) {
        String status = sender.getStatus();
		for (ColleagueItf oneParticipant: participants) {
		    if (oneParticipant.getName().equals(name))
			    sender.updateStatus(status);
		}
    }
}

上述示例的使用方法如下。我们假设有三位老师共同教一门课。老师之间需要同步课程进度。由teacher1上第一节课,由teacher3上最后一节课。所以,在创建了Mediator对象和三位老师对象,并注册完毕之后,由第一位老师将课程状态更新为"Start",以便于通知所有老师课程开始了。在teacher3结束最后一节课之后,将状态更新为"Finish",用以通知所有老师课程结束了。

public class Course {
    public static void main(String[] args) {
	    Mediator mediator = new MediatorImpl();
		
	    ColleagueItf teacher1 = new ColleagueImpl(mediator, "teacher1");
		ColleagueItf teacher2 = new ColleagueImpl(mediator, "teacher2");
		ColleagueItf teacher3 = new ColleagueImpl(mediator, "teacher3");
		
		mediator.register(teacher1);
		mediator.register(teacher2);
		mediator.register(teacher3);
		
		// 课程开始了
		teacher1.setStatus("Start");
		teacher1.syncStatusToColleague("teacher2");
		
		// 继续上课 ...
		
		// 课程结束了
		teacher3.setStatus("Finish")
		teacher3.syncStatus();
	}
}

4 应用示例

Java标准库中也使用了中介者模式。一个典型的用例是java.lang.reflect.Method。当调用invoke方法时,实际上,Java反射机制或者Method扮演者中介者的角色。调用者只需传入被调用的对象,而无需依赖于调用者。另外,java.util.Timer类的schedule()和java.util.concurrent.Executor的execute()方法也使用了中介者模式。在Timer类中,Timer有两个主要的功能。其一是等待超时事件的发生;其二是当超时时,运行一段程序。那么,这第二点实际上使用的是中介者模式,Timer扮演的是中介者。

5 小结

本章介绍了中介者模式的结构和使用方法。它能够简化对象相互交互的复杂度,而且分离了相互交互的逻辑和对象内部的逻辑,因此,当对象相互交互的逻辑发生变化时,不会影响对象内部的逻辑。

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.