交由仲裁者处理-Mediator模式

278 阅读2分钟

1、引入

在工作中,往往遇到组员们各执己见的情况,或许他们各有其道理,但是如果都坚持自己观点互不退让,往往会降低工作效率乃至影响项目。此时,需要一位仲裁者出现,所有的情况告知仲裁者,让仲裁者统一决定,这样可以让使得工作井井有条。

Mediator模式便是则一现实案例在软件中的应用,对于发生过来的请求,统一交给仲裁者处理。

2、示例

实现一个登录界面,可以以游客或是会员身份进入,游客界面密码和账号选项不可用,会员界面必须填写账号和密码后才可以进入。

image.png

2.1、仲裁者接口

所有仲裁者的统一接口:

public interface Mediator {
    public abstract void createColleagues();
    public abstract void colleagueChanged();
}

2.2、各种交互项

2.2.1、统一的向仲裁者报告的接口

public interface Colleague {
    public abstract void setMediator(Mediator mediator);
    public abstract void setColleagueEnabled(Boolean enabled);
}

2.2.2、按钮类

public class ColleagueButton extends Button implements Colleague {
    private Mediator mediator;

    public ColleagueButton(String caption) {
        super(caption);
    }

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

    @Override
    public void setColleagueEnabled(Boolean enabled) {
        setEnabled(enabled);
    }
}

2.2.2、选项类

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);
    }

    public void itemStateChanged(ItemEvent e) {
        mediator.colleagueChanged();
    }
}

2.2.3、文本框类

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

    public ColleagueTextField(String text, int columns) {
        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);
    }

    public void textValueChanged(TextEvent e) {
        mediator.colleagueChanged();
    }
}

2.3、仲裁者实现之LoginFrame

public class LoginFrame extends Frame implements ActionListener,Mediator {
    private ColleagueCheckBox checkGuest;
    private ColleagueCheckBox checkLogin;
    private ColleagueTextField textUser;
    private ColleagueTextField textPass;
    private ColleagueButton buttonOk;
    private ColleagueButton buttonCancel;

    //构建窗口,可以不用在意具体细节,了解即可
    public LoginFrame(String title) throws HeadlessException {
        super(title);
        setBackground(Color.lightGray);
        setLayout(new GridLayout(4,2));
        //创建各个Colleague
        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 actionPerformed(ActionEvent e) {
        System.out.println(e.toString());
        System.exit(0);
    }

    @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);
        //配置监听器
        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 {
            textPass.setColleagueEnabled(false);
            buttonOk.setColleagueEnabled(false);
        }
    }
}

3、tips

  • 在各个交互项中本可以实现对用户操作的反应,但在这里统一交给仲裁者处理,实现了解耦:当需要更改交互逻辑时,只需要更改仲裁者即可。
  • 在许多网页以及客户端制作中,都有着对仲裁者模式的广泛应用。