Definition:
Define an object that encapsulates details and other objects interact with such object.The relationship are loosely decoupled.
Intent:
-> Define an object that encapsulates how a set of objects interfact.Mediator promotes loose coupling from referring to each other explicitly,and it lets us vary their interaction independently.[Gof,p273]
-> Define an intermediary to decouple many peers.
-> Promote the many-to-many relationships between interacting peers to "full object status".
Problem:
We want to redesign reusable components,but dependencies between the potentially reusable pieces demonstates the "spaghetti code" phenomenon (trying to scoop a single serving results in an "all or nothing clump").
Structure Summary:
1) Identify if undue coupling exists between many peer objects.
2) Define a new class that encapsulates how the existing objects interact and decouples the peers from one another.
3) Peer many-to-many relationships have now been objectified.
Overview:
Passes communication between two or more objects.
Wikipedia Says:
Mediator Pattern is a software design pattern that provides a unified interface to a set of interfaces in a subsystem.This pattern is considered a behavior pattern due to the way it can alter the program's running behavior.
Usually a program is made up of a(sometimes large) number of classes.So the logic and computation is distributed among these classes.However as many classes are developed in a program,especially during maintenence and/or refactoring,problem of communication between these classes may become more complex.
This makes the program harder to read and maintain.Furthermore,it can become difficult to change the program,since any change may affect code in several other classes.
Mediator class promotes looser coupling between a number of other classes.It consists of a mediator class that is the only class that has detailed knowledge of the methods of other classes.
Usage and Benefits:
-> Partition a system into pieces or small objects.
-> Centralize control to manipulate participating objects.
-> Improve object re-usabilities.
-> Relationship between control class and other participating classes is multi-directional.
-> Limit Subclasses.
-> Mediator is the only smart delegating object.
-> Most of the complexity involved in managing dependencies is shifted from other objects to the Mediator object.This makes other objects easier to implement and maintain.
CheckList:
1) Identify a collection of interacting objects that would benefit from mutual decoupling.
2) Encapsulate those interactions in the abstraction of a new class.
3) Create an instance of that new class and rework all "peer" objects to interact with the Mediator only.
4) Balance the principle of decoupling with the principle of distributing responsibility evenly.
5) Be careful not to create a "Controller" object.
Related Patterns Include:
Facade: which abstracts a subsystem to provide a more convenient interface,and its protocol is uni-directional,whereas a mediator enables co-operative behavior and its protocol is multidirectional.
Command: Which is used to coordinate functionality.
Observer: which is used in mediator pattern to enhance communication.
Discussion:
In unix,permissions to access system resources is managed at three levels of granuality: world,group and owner.A group is a collection of users intended to model some functional affiliation.Each user on the system can be a member of one or more groups,and each group can have zero or more users assigned to it.
If we were to model this software,we could decide to have User objects coupled to Group objects,and Group objects coupled to User objects.Then when changes occur,both classes and all their instances would be affected.
An alternate approach would be to introduce "an additional level of indirection" - take the mapping of users to groups and groups to users,and make it an abstraction unto itself.This offers several advantages.Users and Groups are decoupled from one another,many mappings can easily be maintained and manipulating simultaneously,and the mapping abstraction can be extended in the future by defining derived classes.
The mediator object: eancapsulates all interconnections,acts as the hub of communication,is responsible for controling and coordinating the interactions of its clients,and promote loose coupling by keeping objects from referring to each other explicitly.
Mediator Pattern promotes a "many-to-many relationship network" to "full object status".Modelling the inter-relationships with an object enhances encapsulation,and allows the behavior of those inter-relationships to be modified or extended through subclassing.
Example:
Mediator defines an object that controls how a set of objects interact.Loose coupling between collegue objects is achieved by having collegues communicate with the Mediator,rather than with each other.The control tower at the airport demonstrates this pattern very well.The pilots of the planes approching or departing the terminal area communicate with the tower rather than explicitly communicating with each other.Constraints on who can take off or land are enforced by the tower.It is important to note that tower does not control the whole flight.It exists only to enforce constraints in the terminal area. [Michael Duell, "Non-software examples of software design patterns", Object Magazine, Jul 97, p54]
Rules of Thumb:
Chain of Responsibility,Command,Mediator and Observer,address how you can decouple senders and receivers,but with different trade-offs.Chain of Responsibility passes a sender request along a chain of potential receivers.Command normally specifies a sender-receiver connection with a subclass.Mediator has senders and receivers reference each other indirectly.Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.[GoF, p347]
Mediator and Observer are competing patterns.The difference between them is is that Observer distributes communication by introducing "observer" and "subject" objects,whereas a Mediator object encapsulates the communication between other objects.We've found it easier to make reusable Observers and Subjects than to make reusable Mediators.[GoF, p346]
On The other hand Mediator can leverage Observer for dynamically registering collegues and communicating with them. [GoF, p282]
Mediator is similar to Facade in that it abstracts functionality of existing classes.Mediator abstracts/centralizes arbitrary communication between colleague objects,it routinely "adds value",and it is known/referenced by the collegue objects.In contrast,Facade defines a similar interface to a subsystem,it doesnot add new functionality,and it is not known by the subsystem classes.(i.e a uni-directional protocol where it makes requests of the subsystem classes.(i.e it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice-versa.) [GoF,p193]
An example of implementation of this pattern is below:
package patterns;
interface Command {
void execute();
}
class ConcurrencyCountry {
private String text;
private Boolean isEnabled=Boolean.FALSE;
public void setText(String text) {
this.text=text;
}
public void setEnabled(Boolean flag) {
this.isEnabled=flag;
}
public Boolean isEnabled() {
return this.isEnabled;
}
public String getText() {
return this.text;
}
}
class DollarCurrencyCountry extends ConcurrencyCountry implements Command {
Mediator med;
public DollarCurrencyCountry(Mediator med) {
this.med=med;
}
public void execute() {
med.enableDollarCurrencyCountries();
}
}
class RupeeCurrencyCountry extends ConcurrencyCountry implements Command {
Mediator med;
public RupeeCurrencyCountry(Mediator med) {
this.med=med;
}
public void execute() {
med.enableRupeeCurrencyCountries();
}
}
class Mediator {
DollarCurrencyCountry dcc;
RupeeCurrencyCountry rcc;
public void registerDollarCurrencyCountries(DollarCurrencyCountry dcc) {
this.dcc=dcc;
}
public void registerRupeeCurrencyCountries(RupeeCurrencyCountry rcc) {
this.rcc=rcc;
}
public void enableDollarCurrencyCountries() {
dcc.setEnabled(Boolean.TRUE);
rcc.setEnabled(Boolean.FALSE);
dcc.setText("Dollar Currency Countries are enabled");
}
public void enableRupeeCurrencyCountries() {
rcc.setEnabled(Boolean.TRUE);
dcc.setEnabled(Boolean.FALSE);
rcc.setText("Rupee Currency Countries are enabled");
}
}
public class MediatorPattern {
public static void main(String[] args) {
Mediator m=new Mediator();
DollarCurrencyCountry dcc=new DollarCurrencyCountry(m);
RupeeCurrencyCountry rcc=new RupeeCurrencyCountry(m);
m.registerDollarCurrencyCountries(dcc);
m.registerRupeeCurrencyCountries(rcc);
dcc.execute();
System.out.println(dcc.getText());
System.out.println(dcc.isEnabled());
System.out.println(rcc.isEnabled());
}
}
Hope this explanation helps if any.
2 comments:
I think you have a error here:
RupeeCurrencyCountry(Mediator med)
{
this.med=med;
}
public void execute()
{
//@ here is the error
//@ med.enableDollarCurrencyCountries();
med.enableRupeeCurrencyCountries()
}
Alexandru,
Thanks a lot for finding a bug.Now it is fixed.
Thanks
Prashant
Post a Comment