Mediator模式

Mediator模式

What

“Mediator”:中介、调解者

(注:在《图解设计模式》一书中,又被译为独裁者,对于这个翻译我还是很认可的,所以中译的话我就沿用书中的译文,独裁者模式)

顾名思义,独裁者模式的核心应当为由一个人来做决定,但是在程序中,经常是多个类根据对方的状态做出不同的反应,这也叫做通信,说的比较抽象,举个例子,比方说A类和B类关联,那么怎么个关联法呢,通常的情形便是A类根据B类的状态而执行某段函数,或者对属性做出某些改变。其实如果只有A、B两个类,那么直接互相通信显然会比使用Mediator模式来得更方便,但是在程序的设计过程中,应当尽量符合开闭原则,也就是对扩展开放,对修改关闭,为了方便拓展,减少代码修改,使用独裁者模式在未来若有C类加入程序,与A,B关联,就无需修改A、B类的代码,仅需在独裁者一处进行修改。

How

创建两个接口,MediatorColleague,通俗的讲也就是老板和员工。

public interface Mediator {
    void createColleagues();
    void colleagueChanged();
}
public interface Colleague {
    void setMediator(Mediator mediator);
    void setColleagueEnabled(boolean enabled);
}

老板处需要有一个招员工的方法,还得给员工留个电话号码,也就是createColleagues()colleagueChanged(),员工需要知道自己的老板是谁,还得执行老板的指示,也就是setMediator()setColleagueEnabled()

上面的是概念老板和概念员工,接下来需要真老板和真员工了。于是创建了LoginFrame类和ColleagueButtonColleagueCheckboxColleagueTextField三个员工类。

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) {
        super(title);
        setBackground(Color.lightGray);
        setLayout(new GridLayout(4, 2));
        createColleagues();
        add(checkGuest);
        add(checkLogin);
        add(new Label("Username:"));
        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");

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

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.toString());
        System.exit(0);
    }
}
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 enable) {
        setEnabled(enable);
    }
}
public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {
    private Mediator mediator;
    public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) {
        super(caption, 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();
    }
}
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);
    }

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

显然,LoginFrame作为老板,首先需要认识员工,然后在让员工们上岗,也就是在createColleagues()里new 出各种各样的员工,然后员工也需要在自己的setMediator()方法里认识老板,在自己准备做决定的时候,给老板打电话,也就是调用老板的colleagueChanged()方法,老板收到电话了,就开始自己根据员工传来的信息开始做决定,指挥员工做事。

以上便是独裁者方法的使用方式。

Why

关于为什么要使用独裁者方法,来给大家列一个指数函数2^n,当只有A,B两个类的,通知状态有两种路径,A>B,B<A。那么当增加一个类,就有6种方法,再加一个就是12种方法,这种代码是真的难写,本着能动脑就少动手的原则,只通知老板岂不是省事很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值