The following is my little chat room system/structure. I've tried to follow the definition/intent of mediator pattern by GoF:
Allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other. Allows for the actions of each object set to vary independently of one another.
But I still have a lot of questions about mediator pattern. This system is my trying and I need any advice about any aspect(pros/cons, alternatives, ...) of my design. All will be deeply appreciated.
These are questions you would ask after review my program:
Q: Why not make the RoomMate an abstract class instead of an interface, so it can keep an reference to the ChatRoom the roommate is currently in?
A: I think an interface would be more useful since a class can implement more than one interfaces in Java. (But all examples I've found from the Internet make Colleague an abstract class and make it keep a reference of Mediator...)
Q: Why do you repeat yourself that Amy, Andy, and Lily all treat the message the same way?
A: Maybe I should consider the strategy pattern. But I just want to focus on the Mediator.
Q: Ok, each concrete mediator knows how many roommates it has. But, reversely, if Lily wants to know how many rooms she has joined?
A: Actually I don't know how to solve this. (But I think maybe that's Lily's responsibility to remember what she's doing)
Role:
- ChatRoom --> Mediator
- RoomMate --> Colleague
UML:
Code:
ChatRoom.java
public abstract class ChatRoom
{
public abstract void accommodate(RoomMate roomMate);
public abstract void fairwell(RoomMate roomMate);
public abstract void sendMessage(RoomMate roomMate, String message);
public abstract void printRoomMates();
public abstract boolean hasRoomMate(RoomMate roomMate);
}
Lounge.java
public class Lounge extends ChatRoom
{
private ArrayList<RoomMate> roomMates;
private String name;
public Lounge() {
this.roomMates = new ArrayList<RoomMate>();
this.name = "Lounge";
}
public void accommodate(RoomMate roomMate) {
getRoomMates().add(roomMate);
}
public void fairwell(RoomMate roomMate) {
if (hasRoomMate(roomMate)) {
roomMates.remove(roomMate);
System.out.format("[%s] Fairwell! %s! we miss you!\n",
getName(),
roomMate.getClass().getSimpleName()
);
} else {
System.out.format("[%s] You can't leave twice! %s\n",
getName(),
roomMate.getClass().getSimpleName()
);
}
}
public void sendMessage(RoomMate roomMate, String message) {
for (RoomMate mate: getRoomMates()) {
if (mate != roomMate) {
mate.receiveMessage(roomMate, message);
}
}
}
public void printRoomMates() {
if (!getRoomMates().isEmpty()) {
System.out.format("[%s] There are:\n", getName());
for (RoomMate mate: getRoomMates()) {
System.out.format(" %s\n", mate.getClass().getSimpleName());
}
} else {
System.out.format("[%s] This room is empty now...\n", getName());
}
}
public boolean hasRoomMate(RoomMate roomMate) {
if (getRoomMates().indexOf(roomMate) >= 0) {
return true;
}
return false;
}
// getter & setter
public String getName() {
return this.name;
}
public ArrayList<RoomMate> getRoomMates() {
return this.roomMates;
}
}
RoomMate.java
public interface RoomMate {
public abstract void receiveMessage(RoomMate roomMate, String message);
}
Amy.java
public class Amy implements RoomMate {
@Override
public void receiveMessage(RoomMate roomMate, String message) {
System.out.format("[%s][receive_message] %s: %s\n",
this.getClass().getSimpleName(),
roomMate.getClass().getSimpleName(),
message
);
}
}
Lily.java
public class Lily implements RoomMate {
@Override
public void receiveMessage(RoomMate roomMate, String message) {
System.out.format("[%s][receive_message] %s: %s\n",
this.getClass().getSimpleName(),
roomMate.getClass().getSimpleName(),
message
);
}
}
Andy.java
public class Andy implements RoomMate {
@Override
public void receiveMessage(RoomMate roomMate, String message) {
System.out.format("[%s][receive_message] %s: %s\n",
this.getClass().getSimpleName(),
roomMate.getClass().getSimpleName(),
message
);
}
}
Main.java
public class Main
{
public static void main(String[] args) {
RoomMate andy = new Andy();
RoomMate amy = new Amy();
RoomMate lily = new Lily();
ChatRoom lounge = new Lounge();
lounge.accommodate(andy);
lounge.printRoomMates();
lounge.accommodate(amy);
lounge.printRoomMates();
lounge.accommodate(lily);
lounge.printRoomMates();
lounge.sendMessage(andy, "Hi everyone :) !");
lounge.sendMessage(lily, "Hello, nice to meet you~ :\")");
lounge.sendMessage(amy, "It's my pleasure to join you! v_v");
lounge.hasRoomMate(andy);
lounge.fairwell(andy);
lounge.fairwell(andy);
lounge.fairwell(amy);
lounge.fairwell(lily);
lounge.printRoomMates();
}
}
The result:
[Lounge] There are:
Andy
[Lounge] There are:
Andy
Amy
[Lounge] There are:
Andy
Amy
Lily
[Amy][receive_message] Andy: Hi everyone :) !
[Lily][receive_message] Andy: Hi everyone :) !
[Andy][receive_message] Lily: Hello, nice to meet you~ :")
[Amy][receive_message] Lily: Hello, nice to meet you~ :")
[Andy][receive_message] Amy: It's my pleasure to join you! v_v
[Lily][receive_message] Amy: It's my pleasure to join you! v_v
[Lounge] Fairwell! Andy! we miss you!
[Lounge] You can't leave twice! Andy
[Lounge] Fairwell! Amy! we miss you!
[Lounge] Fairwell! Lily! we miss you!
[Lounge] This room is empty now...