仲裁者(中介者)模式

236 阅读3分钟

背景

Mediator 是仲裁者,中介者的意思,一方面,当组员发生麻烦事时,通知仲裁者,发生涉及全体组员的事情时也通知仲裁者。当仲裁者下达命令时,组员会立即执行组员向仲裁者报告,仲裁者向组员下达命令。

登场角色

Mediator 仲裁者 中介者

定义与 Colleague 角色 进行通信和做出决定的接口

ConcreteMediator 具体的仲裁者 中介者

实现 Mediator 角色中的接口

Colleague 同事

定义与 Mediator 角色进行通信的接口

ConcreteColleague 具体的同事

实现 Colleague 角色的接口

类图

示例代码

以一个实现一个登录框为例,具有以下的功能:

  1. 选择游客登录,禁用用户名和密码的输入框
  2. 选择用户登录,启用用户名和密码的输入框
  • 如果用户名输入框的文本长度大于1,则启用密码框
  • 如果密码输入框的文本长度大于1,则启用确认按钮
  1. OK按钮只有 用户名和密码输入框中文本长度均大于1时才能启用
  2. Cancle 按钮任何时候均能启用

Colleague

public interface Colleague {
    // 设置仲裁者
    void setMediator(Mediator mediator);

    // 告知组员仲裁者所下达的命令,即仲裁者改变组员的状态
    void setColleagueEnabled(boolean enabled);
}

ColleagueButton

public class ColleagueButton extends Button implements Colleague {

    private Mediator mediator;

    public ColleagueButton(String label) throws HeadlessException {
        super(label);
    }

    @Override
    public void setMediator(Mediator mediator) {  // 保存 mediator
        this.mediator = mediator;
    }

    @Override
    public void setColleagueEnabled(boolean enabled) {  // mediator 下达指令,组员改变状态
        setEnabled(enabled);
    }
}

ColleagueTextField

public class ColleagueTextField extends TextField implements Colleague, TextListener {
    private Mediator mediator;

    public ColleagueTextField(String text, int columns) throws HeadlessException {
        super(text, columns);
    }

    @Override
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    @Override
    public void setColleagueEnabled(boolean enabled) {
        setEnabled(enabled);
        setBackground(enabled ? Color.WHITE : Color.lightGray);
    }

    @Override
    public void textValueChanged(TextEvent e) {  // 告知mediator 自己的状态已经改变
        mediator.colleagueChanged();
    }
}

ColleagueCheckBox

public class ColleagueCheckBox extends Checkbox implements ItemListener, Colleague {

    private Mediator mediator;

    public ColleagueCheckBox(String label, CheckboxGroup group, boolean state) throws HeadlessException {
        super(label, group, state);
    }

    @Override
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    @Override
    public void setColleagueEnabled(boolean enabled) {  // 让仲裁者改变自己的状态
        setEnabled(enabled);
    }

    @Override
    public void itemStateChanged(ItemEvent e) { // 告知仲裁者自己的状态发生变化
        mediator.colleagueChanged();
    }
}

Mediator

public interface Mediator {

    // 创建组员
    void createColleagues();

    // 组员向仲裁者报告,自己的状态发生了改变
    void colleagueChanged();
}

LoginFrame

public class LoginFrame extends Frame implements Mediator, ActionListener {

    private ColleagueButton buttonOk;

    private ColleagueButton buttonCancel;

    private ColleagueCheckBox checkLogin;

    private ColleagueCheckBox checkGuest;

    private ColleagueTextField textUser;

    private ColleagueTextField textPass;

    public LoginFrame(String title) throws HeadlessException {
        super(title);
        setBackground(Color.lightGray);
        setLayout(new GridLayout(4, 2));
        // 创建对象
        createColleagues();

        add(checkGuest);
        add(checkLogin);
        add(new Label("Username:"));
        add(textUser);
        add(new Label("Password:"));
        add(textPass);
        add(buttonOk);
        add(buttonCancel);
        // 设置初始的状态
        colleagueChanged();

        // 显示
        pack();

        show();
    }

    @Override
    public void createColleagues() {
        CheckboxGroup g = new CheckboxGroup();
        checkGuest = new ColleagueCheckBox("Guest", g, true);
        checkLogin = new ColleagueCheckBox("Login", g, false);

        textUser = new ColleagueTextField("", 10);
        textPass = new ColleagueTextField("", 10);
        textPass.setEchoChar('*');

        buttonOk = new ColleagueButton("OK");
        buttonCancel = new ColleagueButton("Cancel");

        // 设置mediator
        checkGuest.setMediator(this);
        checkLogin.setMediator(this);

        textUser.setMediator(this);
        textPass.setMediator(this);
        buttonOk.setMediator(this);
        buttonCancel.setMediator(this);

        // 设置listener
        checkGuest.addItemListener(checkGuest);
        checkLogin.addItemListener(checkLogin);
        textUser.addTextListener(textUser);
        textPass.addTextListener(textPass);
        buttonOk.addActionListener(this);
        buttonCancel.addActionListener(this);
    }

    @Override
    public void colleagueChanged() {
        if (checkGuest.getState()) {
            textUser.setColleagueEnabled(false);
            textPass.setColleagueEnabled(false);
            buttonOk.setColleagueEnabled(true);
        } else {
            textUser.setColleagueEnabled(true);
            userPassChanged();
        }
    }

    private void userPassChanged() {
        if (textUser.getText().length() > 0) {
            textPass.setColleagueEnabled(true);
            if (textPass.getText().length() > 0) {
                buttonOk.setColleagueEnabled(true);
            } else {
                buttonOk.setColleagueEnabled(false);
            }
        } else {
            buttonOk.setColleagueEnabled(false);
            textPass.setColleagueEnabled(false);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.toString());
        System.exit(0);
    }
}

功能分析

  1. 将逻辑处理集中在一个类中,其他类负责调用该方法,可以减少bug查找的时间,只需要查找 Mediator 类中的方法即可,避免将逻辑处理分散到其他类上
  2. ConcreteColleague 角色可以复用,但 ConcreteMediator 类很难复用,因为ConcreteMediator类依赖于特定的应用程序,依赖于特定的逻辑实现;