CHAPTER 18

image

Mediator Patterns

GoF Definition: Define an object that encapsulates how a set of objects interacts. The mediator pattern promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Concept

A mediator is the one who takes the responsibility of communication among a group of objects. The mediator acts as an intermediary who can track the communication between two objects. The other objects in the system are also aware of this mediator and they know that if they need to communicate among themselves, they need to go through the mediator. The advantage of using such a mediator is that we can reduce the direct interconnections among the objects and thus lower the coupling.

Real-Life Example

In an airplane application, before taking off the flight undergoes a series of checks. These checks confirm that all components/parts (which are dependent on each other) are in perfect condition.

Also, the pilot needs to communicate with the towers at the airport. In general, one pilot from one airline will not communicate with another pilot from a different airline before taking off or landing operations. Towers are acting as the mediator here.

Computer World Example

In a business application, in many cases we need to apply constraints (e.g., suppose we have a form for which we need to supply a user id and then a password for that account). In the same form, we may need to supply other mandatory information (e-mail id, communication address, age, etc.). Now suppose the functions are implemented as follows: once a user supplies his user id, the form will check whether that user id (supplied by user) is valid. If it is a valid id, then only the password field will be enabled. After supplying these two fields, we may need to check whether the user has provided any e-mail id. Let’s assume here after providing a user id with a valid e-mail and all other mandatory details, our submit button will be enabled (i.e., the overall submit button will be enabled if we supply a valid user id, password, e-mail id, and other mandatory details only). We must also ensure that the user id is an integer, so if the user by mistake provides any character in that field, the submit button still will be in disabled mode. The mediator pattern becomes handy in such a scenario.

So, when a program consists of many classes and the logic is distributed among them, it becomes harder to read and maintain. If we need to make some kind of change, it becomes a challenging task for us. The mediator pattern is handy in such a scenario.

Illustration

In the example here, we have a group of three friends—Amit, Sohel, and Raghu. Among these three friends, Raghu is the boss and he needs to coordinate things properly. Amit and Sohel work in Raghu’s team. Whenever Amit and Sohel talk to each other (say, through a chat server), Raghu can see who is sending messages to him (though he does not care about the message). Raghu wants to coordinate things smoothly and whenever he wants to send messages, he wants his messages to reach others instantly. Analyze the code and output and it’ll be clear to you.

UML Class Diagram

9781484218013_unFig18-01.jpg

Package Explorer view

High-level structure of the parts of the program is as follows:

9781484218013_unFig18-02.jpg

Implementation

    package mediator.pattern.demo;

    abstract class Mediator
    {
        public abstract void Send(Friend frd, String msg);
    }

    // ConcreteMediator
    class ConcreteMediator extends  Mediator
    {
        private Friend1 friend1;
        private Friend2 friend2;
        private Boss boss;

        //In this example, setters are sufficient.

                public void setFriend1(Friend1 friend1) {
                        this.friend1 = friend1;
                }

                public void setFriend2(Friend2 friend2) {
                        this.friend2 = friend2;
                }

                public void setBoss(Boss boss) {
                        this.boss = boss;
                }

        @Override
        public void Send(Friend frd,String msg)
        {
            //In all cases, boss is notified
            if (frd == friend1)
            {
                friend2.Notify(msg);
                boss.Notify(friend1.name + " sends message to " + friend2.name);
            }
            if(frd==friend2)
            {
                friend1.Notify(msg);
                boss.Notify(friend2.name + " sends message to " + friend1.name);

            }
            //Boss is sending message to others
            if(frd==boss)
            {
                friend1.Notify(msg);
                friend2.Notify(msg);
            }
        }

    }

    // Friend
    abstract class Friend
    {
        protected Mediator mediator;
        public String name;

        // Constructor
        public Friend(Mediator _mediator)
        {
            mediator = _mediator;
        }
    }

    // Friend1—first participant
    class Friend1 extends Friend
    {
        public Friend1(Mediator mediator,String name)
        {
                super(mediator);
            this.name = name;
        }

        public void Send(String msg)
        {
            mediator.Send(this,msg);
        }

        public void Notify(String msg)
        {
                System.out.println("Amit gets message: "+ msg);
        }
    }

    // Friend2—Second participant
    class Friend2 extends Friend
    {
        // Constructor
        public Friend2(Mediator mediator,String name)
        {
            super(mediator);
                this.name = name;
        }

        public void Send(String msg)
        {
            mediator.Send(this,msg);
        }

        public void Notify(String msg)
        {
                System.out.println("Sohel gets message: "+ msg);
        }
    }
    // Friend3—Third participant. He is the boss. He is notified whenever friend1 and friend2 communicate.
    class Boss extends Friend
    {
        // Constructor
        public Boss(Mediator mediator,String name)
        {
                super(mediator);
            this.name = name;
        }

        public void Send(String msg)
        {
            mediator.Send(this, msg);
        }

        public void Notify(String msg)
        {
                System.out.println(" Boss sees message: " + msg);
                System.out.println(“”);
        }
    }

    class MediatorPatternEx
    {
        public static void main(String[] args)
        {
                System.out.println("***Mediator Pattern Demo*** ");
                ConcreteMediator m = new ConcreteMediator();

            Friend1 Amit= new Friend1(m,"Amit");
            Friend2 Sohel = new Friend2(m,"Sohel");
            Boss Raghu = new Boss(m,"Raghu");

            m.setFriend1(Amit);
            m.setFriend2(Sohel);
            m.setBoss(Raghu);

            Amit.Send("[Amit here]Good Morrning. Can we discuss the mediator pattern?");
            Sohel.Send("[Sohel here]Good Morning.Yes, we can discuss now.");
            Raghu.Send(" [Raghu here]:Please get back to work quickly");
        }
    }

Output

9781484218013_unFig18-03.jpg

Note

  1. Now you should have a clear idea that this pattern is very useful when we observe complex communications in the system. Communication (among objects) is much simpler with this pattern.
  2. This pattern reduces the number of subclasses in the system and it also enhances the loose coupling in the system.
  3. Here the “many-to-many” relationship is replaced with the “one-to-many” relationship—which is much easier to read and understand.
  4. We can provide a centralized control with this pattern.
  5. Sometimes the encapsulation process becomes tricky and we find it difficult to maintain or implement.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.37.154