协调多个对象之间的交互 —— 中介者模式

 

中介者模式可以使对象之间的关系数量急剧减少,通过引入中介者对象,可以将系统的网状 结构变成以中介者为中心的星形结构,如图20-5所示。在这个星形结构中,同事对象不再直接 与另一个对象联系,它通过中介者对象与另一个对象发生相互作用。中介者对象的存在保证 了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入带来大量的修改工作。

中介者模式定义如下: 中介者模式(Mediator Pattern):用一个中介对象(中介者)来封装一系列的对象交互,中 介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之 间的交互。

在中介者模式中,我们引入了用于协调其他对象/类之间相互调用的中介者类,为了让系统具 有更好的灵活性和可扩展性,通常还提供了抽象中介者,其结构图如图20-6所示:

在中介者模式结构图中包含如下几个角色:

● Mediator(抽象中介者):它定义一个接口,该接口用于与各同事对象之间进行通信。

● ConcreteMediator(具体中介者):它是抽象中介者的子类,通过协调各个同事对象来实现 协作行为,它维持了对各个同事对象的引用。

● Colleague(抽象同事类):它定义各个同事类公有的方法,并声明了一些抽象方法来供子类 实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。

● ConcreteColleague(具体同事类):它是抽象同事类的子类;每一个同事对象在需要和其他 同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。

在中介者模式中,典型的抽象中介者类代码如下所示:

abstract class Mediator {
protected ArrayList<Colleague> colleagues; //用于存储同事对象
//注册方法,用于增加同事对象
public void register(Colleague colleague) {
colleagues.add(colleague);
}
//声明抽象的业务方法
public abstract void operation();
}

具体中介者类代码如下所示:

 class ConcreteMediator extends Mediator {
//实现业务方法,封装同事之间的调用
public void operation() {
......
((Colleague)(colleagues.get(0))).method1(); //通过中介者调用同事类的方法
......
}
}

在抽象同事类中维持了一个抽象中介者的引用,用于调用中介者的方法,典型的抽象同事类 代码如下所示:

abstract class Colleague {
protected Mediator mediator; //维持一个抽象中介者的引用
public Colleague(Mediator mediator) {
this.mediator=mediator;
}
public abstract void method1(); //声明自身方法,处理自己的行为
//定义依赖方法,与中介者进行通信
public void method2() {
mediator.operation();
}
}

典型的具体同事类代码如下所示:

class ConcreteColleague extends Colleague {
public ConcreteColleague(Mediator mediator) {
super(mediator);
}
//实现自身方法
public void method1() {
......
}
//定义依赖方法,与中介者进行通信
public void method2() {
mediator.operation();
}
}

20.3 完整解决方案

公司开发人员通过分析发现,在图20-2中,界面组件之间存在较为复杂的交互关系:如 果删除一个客户,要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名 称也将减少一个;如果增加一个客户信息,客户列表中需增加一个客户,且组合框中也将增 加一项。

如果实现界面组件之间的交互是公司开发人员必须面对的一个问题?公司开发人员对组件之间的交互关系进行了分析,结果如下:

(1) 当用户单击“增加”按钮、“删除”按钮、“修改”按钮或“查询”按钮时,界面左侧的“客户选择 组合框”、“客户列表”以及界面中的文本框将产生响应。

(2) 当用户通过“客户选择组合框”选中某个客户姓名时,“客户列表”和文本框将产生响应。

(3) 当用户通过“客户列表”选中某个客户姓名时,“客户选择组合框”和文本框将产生响应。 于是,Sunny公司开发人员根据组件之间的交互关系绘制了如图20-3所示初始类图:

 

原方案:

现方案:

为了协调界面组件对象之间的复杂交互关系,Sunny公司开发人员使用中介者模式来设计客户 信息管理窗口,其结构示意图如图20-7所示:

 

 

 

在图20-8中,ConcreteMediator充当具体中介者类,ConcreteMediator维持 了对具体同事类的引用,抽象同事类维持了对抽象中介者的引用。完整代码如下所示:

 抽象中介者:

abstract class Mediator {
public abstract void componentChanged(Component c);
}

具体中介者:

class ConcreteMediator extends Mediator {  
    //维持对各个同事对象的引用  
    public Button addButton;  
    public List list;  
    public TextBox userNameTextBox;  
    public ComboBox cb;  

    //封装同事对象之间的交互  
    public void componentChanged(Component c) {  
        //单击按钮  
if(c == addButton) {  
            System.out.println("--单击增加按钮--");  
            list.update();  
            cb.update();  
            userNameTextBox.update();  
        }  
        //从列表框选择客户  
        else if(c == list) {  
            System.out.println("--从列表框选择客户--");  
            cb.select();  
            userNameTextBox.setText();  
        }  
        //从组合框选择客户  
        else if(c == cb) {  
            System.out.println("--从组合框选择客户--");  
            cb.select();  
            userNameTextBox.setText();  
        }  
    }  
}  

抽象同事类:

abstract class Component {  
    protected Mediator mediator;  

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

    //转发调用  
    public void changed() {  
        mediator.componentChanged(this);  
    }  

    public abstract void update();    
}  

具体同事类:

//按钮类:具体同事类  
class Button extends Component {  
    public void update() {  
        //按钮不产生交互  
    }  
}  

//列表框类:具体同事类  
class List extends Component {  
    public void update() {  
        System.out.println("列表框增加一项:张无忌。");  
    }  

    public void select() {  
        System.out.println("列表框选中项:小龙女。");  
    }  
}  

//组合框类:具体同事类  
class ComboBox extends Component {  
    public void update() {  
        System.out.println("组合框增加一项:张无忌。");  
    }  

    public void select() {  
        System.out.println("组合框选中项:小龙女。");  
    }  
}  

//文本框类:具体同事类  
class TextBox extends Component {  
    public void update() {  
        System.out.println("客户信息增加成功后文本框清空。");  
    }  

    public void setText() {  
        System.out.println("文本框显示:小龙女。");  
    }  
}

编写如下客户端测试代码:

 

class Client {  
    public static void main(String args[]) {  
        //定义中介者对象  
        ConcreteMediator mediator;  
        mediator = new ConcreteMediator();  

        //定义同事对象  
        Button addBT = new Button();  
        List list = new List();  
        ComboBox cb = new ComboBox();  
        TextBox userNameTB = new TextBox();  

        addBT.setMediator(mediator);  
        list.setMediator(mediator);  
        cb.setMediator(mediator);  
        userNameTB.setMediator(mediator);  

        mediator.addButton = addBT;  
        mediator.list = list;  
        mediator.cb = cb;  
        mediator.userNameTextBox = userNameTB;  

        addBT.changed();  
        System.out.println("-----------------------------");  
        list.changed();  
    }  
}

编译并运行程序,输出结果如下:

 

--单击增加按钮--
列表框增加一项:张无忌。
组合框增加一项:张无忌。
客户信息增加成功后文本框清空。
-----------------------------
--从列表框选择客户--
组合框选中项:小龙女。
文本框显示:小龙女。

 

posted @ 2019-01-18 16:16  Archer-Fang  阅读(455)  评论(0)    收藏  举报