代码改变世界

设计模式之中介者模式

2013-06-24 00:27  youxin  阅读(642)  评论(0编辑  收藏  举报

对于那些存在对象之间复杂交互关系的系统,中介者模式提供了一种简化复杂交互的解决方案他通过引入一个中介者,将原本对象之间的两两交互转化为每个对象与中介者之间的交互,中介者可以对对象之间的通信进行控制与协调,极大地降低了原有系统的耦合度,使得系统更加灵活,也更易于扩展。


模式定义:
中介者模式(mediator pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互,中介者模式又称为调停者模式,他是一个对象行为型模式。

 Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

participants

    The classes and/or objects participating in this pattern are:

  • Mediator  (IChatroom)
    • defines an interface for communicating with Colleague objects 定义了一个接口,用于与各同事对象之间通信
  • ConcreteMediator  (Chatroom)
    • implements cooperative behavior by coordinating Colleague objects
    • knows and maintains its colleagues
  • Colleague classes  (Participant)
    • each Colleague class knows its Mediator object
    • each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague

抽象同事类:定义各同事的公有方法。

具体同事类:每一个同事对象都引用一个中介者对象;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中定义的方法。

模式分析:

  中介者模式使得对象之间的关系数量急剧减少,将系统的网状结构变为了以中介者为中心的星状结构。

  如果对象之间存在多对多的相互关系,可以将对象之间的一些交互行为从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行通信和协调,这样对象之间多对多的复杂关系就可以通过相对简单的多对一关系实现。通过引入中介者类简化对象之间的复杂交互,符合迪米特法则,简化了系统的理解和实现。

在这里中介者承担了以下两方面的职责:

1.中转作用(结构性):通过中介者提供的中转作用,各个同事对象就不再需要显示引用其他同事,当需要和其他同事进行通信时,通过中介者即可。该中转作用属于中介者在结构上的支持。

2.协调作用(行为性):中介者可以更进一步对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对同事的请求进行进一步处理,将同事成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持

public abstract class Mediator
{
    protected ArrayList colleagues;
    public void register(Colleague colleague)
    {
        colleagues.add(colleague);
    }
    
    public abstract void operation();
}

在具体中介者类将实现抽象类的抽象方法:

public class ConcreteMediator extends Mediator
{
    public void operation()
    {
        ......
        ((Colleague)(colleagues.get(0))).method1();
        ......
    }
} 

在具体中介者类中将调用同事类的方法,调用时可以增加一些自己的业务代码对调用进行控制。

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

public abstract class Colleague
{
    protected Mediator mediator;
    
    public Colleague(Mediator mediator)
    {
        this.mediator=mediator;
    }
    
    public abstract void method1();
    
    public abstract void method2();
} 

具体同事类:

public class ConcreteColleague extends Colleague
{
    public ConcreteColleague(Mediator mediator)
    {
        super(mediator);
    }
    
    public void method1()
    {
        ......
    }
    
    public void method2()
    {
        mediator.operation1();
    }
} 

在具体同事类中实现了在抽象同事类中声明的方法,其他方法method1()是同事类的自身方法(self-method),用于处理自己的行为,而方法method2()是依赖方法(depend-method),用于调用中介者中定义的方法,依赖中介者来完成相应的行为,例如调用另一个同事类的相关方法

实例:

ü虚拟聊天室
•某论坛系统欲增加一个虚拟聊天室,允许论坛会员通过该聊天室进行信息交流,普通会员(CommonMember)可以给其他会员发送文本信息,钻石会员(DiamondMember)既可以给其他会员发送文本信息,还可以发送图片信息。该聊天室可以对不雅字符进行过滤,如“日”等字符;还可以对发送的图片大小进行控制。用中介者模式设计该虚拟聊天室。
 
 

抽象中介者类:

public abstract class AbstractChatroom {
    public abstract void  register(Member member);
    public abstract void sendText(String from,String to,String message);
    public abstract void sendImage(String from,String to,String image);

}

抽象同事类:

public abstract  class Member {
    protected AbstractChatroom chatroom;
    protected String name;
    
    public Member(String name)
    {
        this.name=name;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name=name;
    }
    public AbstractChatroom getChatroom()
    {
        return chatroom;
    }
    public void setChatroom(AbstractChatroom chatroom)
    {
        this.chatroom=chatroom;
    }
    public abstract void sendText(String to,String message);
    public abstract void sendImage(String to,String image);
    public void receiveText(String from,String message)
    {
        System.out.println(from+"发送文本给 "+this.name+",内容为:"+message);
    }
    public void receiveImage(String from,String image)
    {
        System.out.println(from+"发送图片给 "+this.name+",内容为:"+image);
    }
     
}

由于不同类型的会员发送文本信息和图片信息的方式有所区别,因此在member类中还对这2个方法进行了抽象声明。

具体中介者.

public class ChatGroup extends AbstractChatroom {
    public Hashtable members=new Hashtable();
    @Override
    public void register(Member member) {
        if(!members.contains(member))
        {
            members.put(member.getName(), member);
            member.setChatroom(this);
        }

    }
    

    @Override
    public void sendText(String from, String to, String message) {
        Member member=(Member)members.get(to);
        String newMessage=message;
        newMessage=message.replaceAll("日", "*");
        member.receiveText(from, newMessage);
            

    }

    @Override
    public void sendImage(String from, String to, String image) {
        Member member=(Member)members.get(to);
        //模拟图片大小判断
        if(image.length()>5)
        {
            System.out.println("图片太大,发送失败");
        }
        else
        {
            member.receiveImage(from, image);
        }

    }

}

具体同事类:

public class CommonMember extends Member {
    
    public CommonMember(String name)
    {
        super(name);
    }

    @Override
    public void sendText(String to, String message) {
        System.out.println("普通会员发送信息");
        chatroom.sendText(name, to, message);

    }
    public   void sendImage(String to,String image){
        System.out.println("普通会员不能发送图片");
    }

}
public class DiamondMember extends Member{
    
    public DiamondMember(String name)
    {
        super(name);
    }

    @Override
    public void sendText(String to, String message) {
        System.out.println("钻石会员发送信息");
        chatroom.sendText(name, to, message);

    }
    public   void sendImage(String to,String image){
        System.out.println("钻石会员发送图片");
        chatroom.sendImage(name, to, image);
    }

    
}

会员发送信息时,先发送给中介者,由中介者类对信息进行统一的处理,然后在转发给接收者,在这里,中介者充当了信息发送者和接收者之间的第3者,他在对信息进行过滤进行判断后再对信息进行转发

可以很方便引入新的具体中介者类和同事类。

ü中介者模式的优点
•简化了对象之间的交互。
•将各同事解耦。
•减少子类生成。
•可以简化各同事类的设计和实现。
 
ü中介者模式的缺点
•在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
 
w模式适用环境
ü在以下情况下可以使用中介者模式:
•系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
•一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象
想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的中介者类
 
w模式应用
ü(1) 中介者模式在事件驱动类软件中应用比较多,在设计GUI用程序时,组件之间可能存在较为复杂的交互关系,一个组件的改变将影响与之相关的其他组件,此时可以使用中介者模式来对组件进行协调。
ü(2) MVC Java EE 的一个基本模式,此时控制Controller 作为一种中介者,它负责控制视图对象View和模型对象Model间的交互。如在Struts中,Action就可以作为JSP面与业务对象之间的中介者。
 
 
ü中介者模式与迪米特法则
•在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用
 
–中介者模式与GUI开发
•中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。
•对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。