mediator mode

Article Directory

1. Definition

Definition of GOF
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.
Defines an object that encapsulates the interaction of a set of objects.Intermediator mode decouples objects by eliminating the need for display interaction between them, and allows objects to independently change their interactions.

Just look at the definition, it's not easy to understand. Just look at the picture above and understand in seconds.

Assuming there are five objects, the interaction between them is as follows


Object interaction is complex and difficult to maintain

In the figure below, mediators are introduced, and the interactions between objects are all left to the mediators.
The interaction between objects becomes clear and maintained.

2. Implementation

For example, a chat room, as a Mediator, is responsible for user interaction.
Users don't care how they interact with each other, a typical mediation model.

Users who join chat rooms can receive messages from other users, but they do not have to receive their own messages.
Suppose there are five users user1, user2, user3, user4, user5.
user1, user2, join chat room chat1
User3, user4, user5 join chat2

The scenario is implemented in code below

2.1 cpp implementation

To get into the habit, the cpp sample code for subsequent blogs distinguishes value semantics from object semantics and uses a smart pointer with c++11

//sbkun
#include "noncopyable.h"

#include <iostream>
#include <map>
#include <string>
#include <memory>

using namespace std;
class ChatRoom;

class User: noncopyable {
	public:
		User(const string& name);
		~User() {
			cout<<this<<" "<<name_<<" destruct"<<endl;
		}
		void send(const string& msg);
		void recv(const string& msg);

		void setRoom(weak_ptr<ChatRoom> room) {
			room_ = room;
		}

		const string& getName() const {
			return name_;
		}

	private:
		string name_;
		weak_ptr<ChatRoom> room_;
};

//mediator
class ChatRoom : noncopyable, public enable_shared_from_this<ChatRoom>{
	public:
		typedef map<string, weak_ptr<User>> Room;

		ChatRoom(const string& name) : name_(name) {
		}

		~ChatRoom() {
			cout<<this<<" "<<name_<<" destruct"<<endl;
		}

		void addRoom(shared_ptr<User> user) {
			room_[user->getName()] = user;
			user->setRoom(shared_from_this());
		}

		void send( const string& msg, const string& userName) {
			for(auto const& it: room_) {
				auto pUser = it.second.lock();
				if (pUser) {
					//I don't have to receive my own messages	
					if (pUser->getName() != userName) {
						pUser->recv(msg);
					}
				}
			}
		}

		const string& getName() const {
			return name_;
		}

	private:
		Room room_;
		string name_;
};

User::User(const string& name) : name_(name)
{
}

void User::send(const string& msg) {
	shared_ptr<ChatRoom> pRoom = room_.lock();
	if (pRoom) {
		cout<<name_<<" send "<<msg<<" to "<<pRoom->getName()<<endl;
		pRoom->send(msg, name_);
	}
}

void User::recv(const string& msg) {
	shared_ptr<ChatRoom> pRoom = room_.lock();
	if (pRoom) {
		cout<<getName()<<" recv "<<msg<<" from "<<pRoom->getName()<<endl;
	}
}

int main(int argc, char* argv[])
{
	auto chat1 = make_shared<ChatRoom>("chat1");
	auto chat2 = make_shared<ChatRoom>("chat2");

	auto user1 = make_shared<User>("user1");
	auto user2 = make_shared<User>("user2");
	auto user3 = make_shared<User>("user3");
	auto user4 = make_shared<User>("user4");
	auto user5 = make_shared<User>("user5");

	chat1->addRoom(user1);
	chat1->addRoom(user2);

	chat2->addRoom(user3);
	chat2->addRoom(user4);
	chat2->addRoom(user5);

	user1->send("sbkun");

	cout<<endl;

	user3->send("sbkun");

	cout<<endl;

	return 0;
}

output

[sbkun:designpattern]$ ./mediatordemo
user1 send sbkun to chat1
user2 recv sbkun from chat1

user3 send sbkun to chat2
user4 recv sbkun from chat2
user5 recv sbkun from chat2

2.2 java implementation

//sbkun
package designpattern.mediator;

import java.util.HashMap;
import java.util.Map;

class ChatRoom {
    ChatRoom(String name) {
        this.name = name;
    }

    void addRoot(User user) {
        room.put(user.getName(), user);
        user.setRoom(this);
    }

    void send(String msg, String userName) {
        for(Map.Entry<String, User> entry: room.entrySet()) {
            if (!entry.getKey().equals(userName)) {
                User user = entry.getValue();
                user.recv(msg);
            }
        }
    }

    public String getName() {
        return name;
    }

    private String name;
    private Map<String, User> room = new HashMap<String, User>();
}

class User {
    User(String name) {
        this.name = name;
    }

    void send(String msg) {
        if (room != null) {
            System.out.println(name + " send " + msg + " to " + room.getName());
            room.send(msg, name);
        }
    }

    void recv(String msg) {
        if (room != null) {
            System.out.println(name + " recv " + msg + " from " + room.getName());
        }
    }

    public String getName() {
        return name;
    }

    public void setRoom(ChatRoom room) {
        this.room = room;
    }

    private String name;

    private ChatRoom room = null;
}

public class MediatorDemo {
    static public void main(String args[]) {
        ChatRoom chat1 = new ChatRoom("chat1");
        ChatRoom chat2 = new ChatRoom("chat2");

        User user1 = new User("user1");
        User user2 = new User("user2");
        User user3 = new User("user3");
        User user4 = new User("user4");
        User user5 = new User("user5");

        chat1.addRoot(user1);
        chat1.addRoot(user2);

        chat2.addRoot(user3);
        chat2.addRoot(user4);
        chat2.addRoot(user5);

        user1.send("sbkun");

        System.out.println("");

        user3.send("sbkun");
    }
}

4. Full code address

All the code for this column has been uploaded to github. I hope you can criticize and correct it a lot
[git link] (https://github.com/uyghfjhh/designpattern.git

Tags: Java github git

Posted on Fri, 05 Jun 2020 09:18:00 -0700 by Ben Cleary