Singleton Design Pattern
Singleton design pattern is a creational design pattern that restricts the initialization of objects. This pattern ensures that at any point of time there is only one instance of the object within the application context. And the singleton design also pattern requires that there should be a global point to access the object.
Singleton design pattern should provide the flexibility of creating multiple instances if the situation demands at a later stage, without affecting classes that are using the singleton object.
Any fields defined in the singleton class would act as static fields; as only one instance of the class would be created. Singletons can be used in place of the global variables.
The singleton pattern may be used for an application wide resource, like the logger or implement a state object.
Implementing Singleton Design Pattern
To implement the singleton design pattern, you need to:
Example of a Singleton class
public class MySingleton
{
private static MySingleton instance; // Private Contructor
private MySingleton() { } // Lazy initialization
public static synchronized MySingleton getInstance()
{
if (instance == null)
{
instance = new MySingleton();
}
return instance;
}
}
The above example uses the lazy initiation as the instance of the class would not be created until the getInstance() method is called for the first time.
Cloning can create problems as will allow you create a copy of the singleton object. Thus to avoid cloning the clone() method should be overridden.
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
Builder Pattern
The builder pattern is a creational design pattern used to assemble complex objects. With the builder pattern, the same object construction process can be used to create different objects.
The builder has 4 main parts:
a Builder,
Concrete Builders,
a Director,
and a Product.
A Builder is an interface (or abstract class) that is implemented (or extended) by Concrete Builders. The Builder interface sets forth the actions (methods) involved in assembling a Product object. It also has a method for retrieving the Product object (ie, getProduct()). The Product object is the object that gets assembled in the builder pattern.
Concrete Builders implement the Builder interface (or extend the Builder abstract class). A Concrete Builder is responsible for creating and assembling a Product object. Different Concrete Builders create and assemble Product objects differently.
A Director object is responsible for constructing a Product. It does this via the Builder interface to a Concrete Builder. It constructs a Product via the various Builder methods.
There are various uses of the builder pattern. For one, if we'd like the construction process to remain the same but we'd like to create a different type of Product, we can create a new Concrete Builder and pass this to the same Director. If we'd like to alter the construction process, we can modify the Director to use a different construction process.
Now, let's look at an example of the builder pattern. Our example will build different kinds of restaurant meals.
First off, our Product will be a Meal class, which represents food items in a meal. It represents a drink, main course, and side item.
Meal.java
package com.cakes;
public class Meal {
private String drink;
private String mainCourse;
private String side;
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
public String getMainCourse() {
return mainCourse;
}
public void setMainCourse(String mainCourse) {
this.mainCourse = mainCourse;
}
public String getSide() {
return side;
}
public void setSide(String side) {
this.side = side;
}
public String toString() {
return "drink:" + drink + ", main course:" + mainCourse + ", side:" + side;
}
}
Our Builder interface is MealBuilder. It features methods used to build a meal and a method to retrieve the meal.
MealBuilder.java
package com.cakes;
public interface MealBuilder {
public void buildDrink();
public void buildMainCourse();
public void buildSide();
public Meal getMeal();
}
Our first Concrete Builder is ItalianMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of the meal. It returns the meal via getMeal().
ItalianMealBuilder.java
package com.cakes;
public class ItalianMealBuilder implements MealBuilder {
private Meal meal;
public ItalianMealBuilder() {
meal = new Meal();
}
@Override
public void buildDrink() {
meal.setDrink("red wine");
}
@Override
public void buildMainCourse() {
meal.setMainCourse("pizza");
}
@Override
public void buildSide() {
meal.setSide("bread");
}
@Override
public Meal getMeal() {
return meal;
}
}
Our second Concrete Builder is JapaneseMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of a Japanese meal. It returns the meal via getMeal().
JapaneseMealBuilder.java
package com.cakes;
public class JapaneseMealBuilder implements MealBuilder {
private Meal meal;
public JapaneseMealBuilder() {
meal = new Meal();
}
@Override
public void buildDrink() {
meal.setDrink("sake");
}
@Override
public void buildMainCourse() {
meal.setMainCourse("chicken teriyaki");
}
@Override
public void buildSide() {
meal.setSide("miso soup");
}
@Override
public Meal getMeal() {
return meal;
}
}
Our Director class is MealDirector. It takes a MealBuilder as a parameter in its constructor. Thus, a different type of meal will be assembled by the MealDirector depending on the Concrete Builder passed in to the constructor. The assembly of the meal (Product) takes place in the constructMeal() method of the Director. This method spells out the parts of the meal that will be assembled.
MealDirector.java
package com.cakes;
public class MealDirector {
private MealBuilder mealBuilder = null;
public MealDirector(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public void constructMeal() {
mealBuilder.buildDrink();
mealBuilder.buildMainCourse();
mealBuilder.buildSide();
}
public Meal getMeal() {
return mealBuilder.getMeal();
}
}
The Demo class lets us demonstrate our builder pattern. First, our director builds an Italian meal. An ItalianMealBuilder is passed to the MealDirector's constructor. The meal is constructed via mealDirector.constructMeal(). The meal is obtained from mealDirector via mealDirector.getMeal(). The Italian meal is displayed. After this, we perform the same process to build and display a Japanese meal.
Demo.java
package com.cakes;
public class Demo {
public static void main(String[] args) {
MealBuilder mealBuilder = new ItalianMealBuilder();
MealDirector mealDirector = new MealDirector(mealBuilder);
mealDirector.constructMeal();
Meal meal = mealDirector.getMeal();
System.out.println("meal is: " + meal);
mealBuilder = new JapaneseMealBuilder();
mealDirector = new MealDirector(mealBuilder);
mealDirector.constructMeal();
meal = mealDirector.getMeal();
System.out.println("meal is: " + meal);
}
}
The console output of executing Demo is shown here.
Console Output
meal is: drink:red wine, main course:pizza, side:bread
meal is: drink:sake, main course:chicken teriyaki, side:miso soup
Notice that if we'd like to create a new type of meal, we can do so by implementing a new Concrete Builder (ie, SwedishMealBuilder, FrenchMealBuilder, etc), which we'd pass to the MealDirector. If we'd like the meal to be constructed of different parts (ie, no drink), we can alter the construction process in MealDirector. Thus, construction process has been separated to the Director, and the data representation is controlled by the Concrete Builders that implement the Builder interface.
Mediator Pattern
Behavioral design pattern can change the way programs run. Mediator design pattern is one of the important and widely used behavioral design pattern. Mediator enables decoupling of objects by introducing a layer in between so that the interaction between objects happen via the layer.
In an enterprise application where we have large number of classes the complexity also increases proportionately. Business logic might be spread across those multiple classes. There will be interaction between classes.
Before Mediator Design Pattern
So what is the problem we are trying to solve here? This complex interaction between objects creates dependency and tighter coupling. We stand for loose coupling, we want to reduce dependency as much as possible, we want more reuse.
Singleton design pattern is a creational design pattern that restricts the initialization of objects. This pattern ensures that at any point of time there is only one instance of the object within the application context. And the singleton design also pattern requires that there should be a global point to access the object.
Singleton design pattern should provide the flexibility of creating multiple instances if the situation demands at a later stage, without affecting classes that are using the singleton object.
Any fields defined in the singleton class would act as static fields; as only one instance of the class would be created. Singletons can be used in place of the global variables.
The singleton pattern may be used for an application wide resource, like the logger or implement a state object.
Implementing Singleton Design Pattern
To implement the singleton design pattern, you need to:
- Declare the constructor of the class as private so that the class cannot be instantiated by any other class.
- Declare a public static method to get the instance of the class, so that the method that method can control the number instance that can be created. The method should also be thread safe.
Example of a Singleton class
public class MySingleton
{
private static MySingleton instance; // Private Contructor
private MySingleton() { } // Lazy initialization
public static synchronized MySingleton getInstance()
{
if (instance == null)
{
instance = new MySingleton();
}
return instance;
}
}
The above example uses the lazy initiation as the instance of the class would not be created until the getInstance() method is called for the first time.
Cloning can create problems as will allow you create a copy of the singleton object. Thus to avoid cloning the clone() method should be overridden.
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
Builder Pattern
The builder pattern is a creational design pattern used to assemble complex objects. With the builder pattern, the same object construction process can be used to create different objects.
The builder has 4 main parts:
a Builder,
Concrete Builders,
a Director,
and a Product.
A Builder is an interface (or abstract class) that is implemented (or extended) by Concrete Builders. The Builder interface sets forth the actions (methods) involved in assembling a Product object. It also has a method for retrieving the Product object (ie, getProduct()). The Product object is the object that gets assembled in the builder pattern.
Concrete Builders implement the Builder interface (or extend the Builder abstract class). A Concrete Builder is responsible for creating and assembling a Product object. Different Concrete Builders create and assemble Product objects differently.
A Director object is responsible for constructing a Product. It does this via the Builder interface to a Concrete Builder. It constructs a Product via the various Builder methods.
There are various uses of the builder pattern. For one, if we'd like the construction process to remain the same but we'd like to create a different type of Product, we can create a new Concrete Builder and pass this to the same Director. If we'd like to alter the construction process, we can modify the Director to use a different construction process.
Now, let's look at an example of the builder pattern. Our example will build different kinds of restaurant meals.
First off, our Product will be a Meal class, which represents food items in a meal. It represents a drink, main course, and side item.
Meal.java
package com.cakes;
public class Meal {
private String drink;
private String mainCourse;
private String side;
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
public String getMainCourse() {
return mainCourse;
}
public void setMainCourse(String mainCourse) {
this.mainCourse = mainCourse;
}
public String getSide() {
return side;
}
public void setSide(String side) {
this.side = side;
}
public String toString() {
return "drink:" + drink + ", main course:" + mainCourse + ", side:" + side;
}
}
Our Builder interface is MealBuilder. It features methods used to build a meal and a method to retrieve the meal.
MealBuilder.java
package com.cakes;
public interface MealBuilder {
public void buildDrink();
public void buildMainCourse();
public void buildSide();
public Meal getMeal();
}
Our first Concrete Builder is ItalianMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of the meal. It returns the meal via getMeal().
ItalianMealBuilder.java
package com.cakes;
public class ItalianMealBuilder implements MealBuilder {
private Meal meal;
public ItalianMealBuilder() {
meal = new Meal();
}
@Override
public void buildDrink() {
meal.setDrink("red wine");
}
@Override
public void buildMainCourse() {
meal.setMainCourse("pizza");
}
@Override
public void buildSide() {
meal.setSide("bread");
}
@Override
public Meal getMeal() {
return meal;
}
}
Our second Concrete Builder is JapaneseMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of a Japanese meal. It returns the meal via getMeal().
JapaneseMealBuilder.java
package com.cakes;
public class JapaneseMealBuilder implements MealBuilder {
private Meal meal;
public JapaneseMealBuilder() {
meal = new Meal();
}
@Override
public void buildDrink() {
meal.setDrink("sake");
}
@Override
public void buildMainCourse() {
meal.setMainCourse("chicken teriyaki");
}
@Override
public void buildSide() {
meal.setSide("miso soup");
}
@Override
public Meal getMeal() {
return meal;
}
}
Our Director class is MealDirector. It takes a MealBuilder as a parameter in its constructor. Thus, a different type of meal will be assembled by the MealDirector depending on the Concrete Builder passed in to the constructor. The assembly of the meal (Product) takes place in the constructMeal() method of the Director. This method spells out the parts of the meal that will be assembled.
MealDirector.java
package com.cakes;
public class MealDirector {
private MealBuilder mealBuilder = null;
public MealDirector(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public void constructMeal() {
mealBuilder.buildDrink();
mealBuilder.buildMainCourse();
mealBuilder.buildSide();
}
public Meal getMeal() {
return mealBuilder.getMeal();
}
}
The Demo class lets us demonstrate our builder pattern. First, our director builds an Italian meal. An ItalianMealBuilder is passed to the MealDirector's constructor. The meal is constructed via mealDirector.constructMeal(). The meal is obtained from mealDirector via mealDirector.getMeal(). The Italian meal is displayed. After this, we perform the same process to build and display a Japanese meal.
Demo.java
package com.cakes;
public class Demo {
public static void main(String[] args) {
MealBuilder mealBuilder = new ItalianMealBuilder();
MealDirector mealDirector = new MealDirector(mealBuilder);
mealDirector.constructMeal();
Meal meal = mealDirector.getMeal();
System.out.println("meal is: " + meal);
mealBuilder = new JapaneseMealBuilder();
mealDirector = new MealDirector(mealBuilder);
mealDirector.constructMeal();
meal = mealDirector.getMeal();
System.out.println("meal is: " + meal);
}
}
The console output of executing Demo is shown here.
Console Output
meal is: drink:red wine, main course:pizza, side:bread
meal is: drink:sake, main course:chicken teriyaki, side:miso soup
Notice that if we'd like to create a new type of meal, we can do so by implementing a new Concrete Builder (ie, SwedishMealBuilder, FrenchMealBuilder, etc), which we'd pass to the MealDirector. If we'd like the meal to be constructed of different parts (ie, no drink), we can alter the construction process in MealDirector. Thus, construction process has been separated to the Director, and the data representation is controlled by the Concrete Builders that implement the Builder interface.
Mediator Pattern
Behavioral design pattern can change the way programs run. Mediator design pattern is one of the important and widely used behavioral design pattern. Mediator enables decoupling of objects by introducing a layer in between so that the interaction between objects happen via the layer.
In an enterprise application where we have large number of classes the complexity also increases proportionately. Business logic might be spread across those multiple classes. There will be interaction between classes.
Before Mediator Design Pattern
So what is the problem we are trying to solve here? This complex interaction between objects creates dependency and tighter coupling. We stand for loose coupling, we want to reduce dependency as much as possible, we want more reuse.
After Mediator Design
Pattern Define an object that acts as a mediator between communicating objects thus removing the direct dependency between those communicating objects. This mediator object encapsulates the interaction information and uses it to enable communication between the objects.
Pattern Define an object that acts as a mediator between communicating objects thus removing the direct dependency between those communicating objects. This mediator object encapsulates the interaction information and uses it to enable communication between the objects.
The intermediate mediator object is not only to communicate between two objects, but it helps in interaction for a set of peer objects. This mediator object is like a router in networks, which is routes / controls or coordinates communication between systems.
Real-time Example for Mediator Design Pattern
Air traffic controller (ATC) is a mediator between flights. It helps in communication between flights and co-oridates/controls landing, take-off. Two flights need not interact directly and there is no dependency between them. This dependency is solved by the mediator ATC. If ATC is not there all the flights have to interact with one another and managing the show will be very difficult and things may go wrong.
Real-time Example for Mediator Design Pattern
Air traffic controller (ATC) is a mediator between flights. It helps in communication between flights and co-oridates/controls landing, take-off. Two flights need not interact directly and there is no dependency between them. This dependency is solved by the mediator ATC. If ATC is not there all the flights have to interact with one another and managing the show will be very difficult and things may go wrong.
Mediator Pattern Implementation
In a mediator design pattern implementation we will have
Java Example for Mediator Desing Pattern
package com.javapapers.designpattern.mediator;
public class ATCMediator implements IATCMediator {
private Flight flight;
private Runway runway;
public boolean land;
public void registerRunway(Runway runway) {
this.runway = runway;
}
public void registerFlight(Flight flight) {
this.flight = flight;
}
public boolean isLandingOk() {
return land;
}
@Override
public void setLandingStatus(boolean status) {
land = status; }
}
package com.javapapers.designpattern.mediator;
public interface Command {
void land();
}
package com.javapapers.designpattern.mediator;
public interface IATCMediator {
public void registerRunway(Runway runway);
public void registerFlight(Flight flight);
public boolean isLandingOk();
public void setLandingStatus(boolean status);
}
package com.javapapers.designpattern.mediator;
public class Flight implements Command {
private IATCMediator atcMediator;
public Flight(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
}
public void land()
{
if (atcMediator.isLandingOk()) {
System.out.println("Landing done....");
atcMediator.setLandingStatus(true);
}
else
System.out.println("Will wait to land....");
}
public void getReady() {
System.out.println("Getting ready...");
}
}
package com.javapapers.designpattern.mediator;
public class Runway implements Command
{
private IATCMediator atcMediator;
public Runway(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
atcMediator.setLandingStatus(true);
}
@Override
public void land() {
System.out.println("Landing permission granted...");
atcMediator.setLandingStatus(true);
}
}
MediatorDesignPattern.java
package com.javapapers.designpattern.mediator;
public class MediatorDesignPattern {
public static void main(String args[]) {
IATCMediator atcMediator = new ATCMediator();
Flight sparrow101 = new Flight(atcMediator);
Runway mainRunway = new Runway(atcMediator);
atcMediator.registerFlight(sparrow101);
atcMediator.registerRunway(mainRunway);
sparrow101.getReady();
mainRunway.land();
sparrow101.land();
}
}
Source : http://javapapers.com/design-patterns/mediator-design-pattern/
Adapter Pattern
It is a structural design pattern. The Adapter pattern is used so that two unrelated interfaces can work together. The joining between them is called an Adapter. This is something like we convert interface of one class into interface expected by the client. We do that using an Adapter.
Let’s try and understand this with the help of an example. Again, I will like to take a general example. We all have electric sockets in our houses of different sizes and shapes. I will take an example of a socket of 15 Ampere. This is a bigger socket and the other one which is smaller is of 5 Ampere. A 15 Amp plug cannot fit into a 5 Amp socket. Here, we will use an Adapter. The adapter can be called a connector here. The connector connects both of these and gives output to the client plug which is of 5 Amp.
The Adapter is something like this. It will be having the plug of suitable for 15 Amp and a socket suitable for a 5 Amp plug. So, that the 5 Amp plug which here is the client can fit in and also the server which here is the 15 Amp socket can give the output.
Benefits:
1. It allows two or more previously incompatible objects to interact.
2. It allows reusability of existing functionality.
The Adapter Pattern can be implemented in two ways, by Inheritance and by Composition.
Here is the example of Adapter by Inheritance:
Let’s say there is a socket interface.
Socket.java
package structural.adapter.inheritance;
/**
* The socket class has a specs for 15 AMP.
*/
public interface Socket { /**
* This method is used to match the input to be
* given to the Plug
*
* @return Output of the Plug (Client)
*/
public String getOutput(); }
// End of interface
And there is a class Plug which wants the input of 5 AMP. This is the client.
Plug.java
package structural.adapter.inheritance;
/**
* The input for the plug is 5 AMP. which is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater to
* the requirements of the Plug.
*/
public class Plug {
private String specification = "5 AMP";
public String getInput() {
return specification;
}
}// End of class
Finally, there will be an adapter class. This will inherit the socket and give output for Plug.
ConnectorAdapter.java
package structural.adapter.inheritance;
/**
* ConnectorAdapter has is the connector between
* the socket and plug so as to make the interface
* of one system to suit the client.
*/
public class ConnectorAdapter implements Socket { /**
* Method coming from the interface
* Socket which we have to make to
* fit the client plug
*
* @return Desired output of 5 AMP
*/
public String getOutput() {
Plug plug = new Plug();
String output = plug.getInput();
return output;
}
}// End of class
This class implements the getOutput() method of Socket and sets it to fit the client output.
Similarly, let’s consider the Association and Composition of objects by which Adapter can be implemented.
The class Socket gives the 15 AMP output.
Socket.java
package structural.adapter.composition;
/**
* Class socket giving the 15 AMP output.
*/
public class Socket { /**
* Output of 15AMP returned.
*
* @return Value of output from socket
*/
public String getOutput() {
return "15 AMP";
}
}/
/ End of class
There is an interface Plug.java which has a method getInput(). This is the client and we need to adapt the output for this input which is 5 AMP.
Plug.java
package structural.adapter.composition;
/**
* The input for the plug is 5 AMP. which is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater to
* the requirements of the Plug.
*/
public interface Plug {
public String getInput();
}
// End of class Plug
5AMP is the implementation of Plug which requires 5 AMP of input.
Plug5AMP.java
package structural.adapter.composition;
public class Plug5AMP implements Plug { /**
* Get the input of client i.e. Plug
*
* @return 5 AMP
*/
public String getInput() {
return "5 AMP";
}
}// End of class
The Adapter here takes output from the Socket. If the output is what is needed, it gives it to the Plug else, it overrides the value and returns the adapter output.
ConnectorAdapter.java
package structural.adapter.composition;
/**
* Using composition
*/
public class ConnectorAdapter {
Plug5AMP plug5;
public ConnectorAdapter(Plug5AMP plug) {
this.plug5 = plug;
}
public static void main(String[] args) {
// Taking output from the Socket
Socket socket = new Socket();
String outputFromSocket = socket.getOutput();
// Giving away input to the Plug
ConnectorAdapter adapter = new ConnectorAdapter(new Plug5AMP());
String inputToPlug = adapter.getAdapterOutput(outputFromSocket);
System.out.println("New output by adapter is: "+inputToPlug);
}
public String getAdapterOutput(String outputFromScoket) {
/*
* if output is same, return
*/
if (outputFromScoket.equals(plug5.getInput())) {
return outputFromScoket;
}
/*
* Else, override the value by adapterOutput
*/
else {
String adapterOutput = plug5.getInput();
return adapterOutput;
}
}// End of class
This is how the Adapter pattern works. When one interface cannot be changed and has to be suited to the again cannot-be-changed client, an adapter is used so that both the interfaces can work together.
The adapter pattern takes two forms.
In the first form, a "class adapter" utilizes inheritance. The class adapter extends the adaptee class and adds the desired methods to the adapter. These methods can be declared in an interface(i.e the "Target" interface).
In the second form, an "object adapter" utilizes composition. The object adapter contains an adaptee & implements target interface to interact with adaptee.
Below example is from Sun Certified Enterprise Architect book:
package j2ee.architect.Adapter;
public class AdapterPattern {
public static void main(String[] args) {
System.out.println("Adapter Pattern Demonstration.");
System.out.println("------------------------------");
// Create targets.
System.out.println("Creating targets.");
TargetIF target1 = new AdapterByClass();
TargetIF target2 = new AdapterByObject();
// Call target requests
System.out.println("Calling targets.");
System.out.println("target1.newRequest()->"+target1.newRequest());
System.out.println("target2.newRequest()->"+target2.newRequest());
System.out.println();
}
}
package j2ee.architect.Adapter;
public class Adaptee {
public Adaptee() {
System.out.println("Adaptee constructed.");
}
public String oldRequest() {
return "Adaptee.oldRequest() called.";
}
}
package j2ee.architect.Adapter;
public class AdapterByClass extends Adaptee implements TargetIF {
public AdapterByClass() {
System.out.println("AdapterByClass constructed.");
}
public String newRequest() {
return oldRequest();
}
}
package j2ee.architect.Adapter;
public class AdapterByObject implements TargetIF {
private Adaptee adaptee;
public AdapterByObject() {
System.out.println("AdapterByObject constructed.");
}
public String newRequest() {
// Create an Adaptee object if it doesn't exist yet
if (adaptee == null) { adaptee = new Adaptee(); }
return adaptee.oldRequest();
}
}
package j2ee.architect.Adapter;
public interface TargetIF {
public String newRequest();
}
Example: In the EJB implementation model, we implement an EJB in a class that extends Session Bean or Entity Bean. We don't directly implement the EJBObject/home interfaces. EJB container generates a class that adapts the EJBobject Interface by forwarding the calls to the enterpise bean class & provides declarative transaction, persistence support.
In a mediator design pattern implementation we will have
- mediator interface – an interface that defines the communication rules between objects
- concrete mediator – a mediator object which will enables communication between participating objects
- colleague – objects communicating with each other through mediator object
Java Example for Mediator Desing Pattern
package com.javapapers.designpattern.mediator;
public class ATCMediator implements IATCMediator {
private Flight flight;
private Runway runway;
public boolean land;
public void registerRunway(Runway runway) {
this.runway = runway;
}
public void registerFlight(Flight flight) {
this.flight = flight;
}
public boolean isLandingOk() {
return land;
}
@Override
public void setLandingStatus(boolean status) {
land = status; }
}
package com.javapapers.designpattern.mediator;
public interface Command {
void land();
}
package com.javapapers.designpattern.mediator;
public interface IATCMediator {
public void registerRunway(Runway runway);
public void registerFlight(Flight flight);
public boolean isLandingOk();
public void setLandingStatus(boolean status);
}
package com.javapapers.designpattern.mediator;
public class Flight implements Command {
private IATCMediator atcMediator;
public Flight(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
}
public void land()
{
if (atcMediator.isLandingOk()) {
System.out.println("Landing done....");
atcMediator.setLandingStatus(true);
}
else
System.out.println("Will wait to land....");
}
public void getReady() {
System.out.println("Getting ready...");
}
}
package com.javapapers.designpattern.mediator;
public class Runway implements Command
{
private IATCMediator atcMediator;
public Runway(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
atcMediator.setLandingStatus(true);
}
@Override
public void land() {
System.out.println("Landing permission granted...");
atcMediator.setLandingStatus(true);
}
}
MediatorDesignPattern.java
package com.javapapers.designpattern.mediator;
public class MediatorDesignPattern {
public static void main(String args[]) {
IATCMediator atcMediator = new ATCMediator();
Flight sparrow101 = new Flight(atcMediator);
Runway mainRunway = new Runway(atcMediator);
atcMediator.registerFlight(sparrow101);
atcMediator.registerRunway(mainRunway);
sparrow101.getReady();
mainRunway.land();
sparrow101.land();
}
}
Source : http://javapapers.com/design-patterns/mediator-design-pattern/
Adapter Pattern
It is a structural design pattern. The Adapter pattern is used so that two unrelated interfaces can work together. The joining between them is called an Adapter. This is something like we convert interface of one class into interface expected by the client. We do that using an Adapter.
Let’s try and understand this with the help of an example. Again, I will like to take a general example. We all have electric sockets in our houses of different sizes and shapes. I will take an example of a socket of 15 Ampere. This is a bigger socket and the other one which is smaller is of 5 Ampere. A 15 Amp plug cannot fit into a 5 Amp socket. Here, we will use an Adapter. The adapter can be called a connector here. The connector connects both of these and gives output to the client plug which is of 5 Amp.
The Adapter is something like this. It will be having the plug of suitable for 15 Amp and a socket suitable for a 5 Amp plug. So, that the 5 Amp plug which here is the client can fit in and also the server which here is the 15 Amp socket can give the output.
Benefits:
1. It allows two or more previously incompatible objects to interact.
2. It allows reusability of existing functionality.
The Adapter Pattern can be implemented in two ways, by Inheritance and by Composition.
Here is the example of Adapter by Inheritance:
Let’s say there is a socket interface.
Socket.java
package structural.adapter.inheritance;
/**
* The socket class has a specs for 15 AMP.
*/
public interface Socket { /**
* This method is used to match the input to be
* given to the Plug
*
* @return Output of the Plug (Client)
*/
public String getOutput(); }
// End of interface
And there is a class Plug which wants the input of 5 AMP. This is the client.
Plug.java
package structural.adapter.inheritance;
/**
* The input for the plug is 5 AMP. which is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater to
* the requirements of the Plug.
*/
public class Plug {
private String specification = "5 AMP";
public String getInput() {
return specification;
}
}// End of class
Finally, there will be an adapter class. This will inherit the socket and give output for Plug.
ConnectorAdapter.java
package structural.adapter.inheritance;
/**
* ConnectorAdapter has is the connector between
* the socket and plug so as to make the interface
* of one system to suit the client.
*/
public class ConnectorAdapter implements Socket { /**
* Method coming from the interface
* Socket which we have to make to
* fit the client plug
*
* @return Desired output of 5 AMP
*/
public String getOutput() {
Plug plug = new Plug();
String output = plug.getInput();
return output;
}
}// End of class
This class implements the getOutput() method of Socket and sets it to fit the client output.
Similarly, let’s consider the Association and Composition of objects by which Adapter can be implemented.
The class Socket gives the 15 AMP output.
Socket.java
package structural.adapter.composition;
/**
* Class socket giving the 15 AMP output.
*/
public class Socket { /**
* Output of 15AMP returned.
*
* @return Value of output from socket
*/
public String getOutput() {
return "15 AMP";
}
}/
/ End of class
There is an interface Plug.java which has a method getInput(). This is the client and we need to adapt the output for this input which is 5 AMP.
Plug.java
package structural.adapter.composition;
/**
* The input for the plug is 5 AMP. which is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater to
* the requirements of the Plug.
*/
public interface Plug {
public String getInput();
}
// End of class Plug
5AMP is the implementation of Plug which requires 5 AMP of input.
Plug5AMP.java
package structural.adapter.composition;
public class Plug5AMP implements Plug { /**
* Get the input of client i.e. Plug
*
* @return 5 AMP
*/
public String getInput() {
return "5 AMP";
}
}// End of class
The Adapter here takes output from the Socket. If the output is what is needed, it gives it to the Plug else, it overrides the value and returns the adapter output.
ConnectorAdapter.java
package structural.adapter.composition;
/**
* Using composition
*/
public class ConnectorAdapter {
Plug5AMP plug5;
public ConnectorAdapter(Plug5AMP plug) {
this.plug5 = plug;
}
public static void main(String[] args) {
// Taking output from the Socket
Socket socket = new Socket();
String outputFromSocket = socket.getOutput();
// Giving away input to the Plug
ConnectorAdapter adapter = new ConnectorAdapter(new Plug5AMP());
String inputToPlug = adapter.getAdapterOutput(outputFromSocket);
System.out.println("New output by adapter is: "+inputToPlug);
}
public String getAdapterOutput(String outputFromScoket) {
/*
* if output is same, return
*/
if (outputFromScoket.equals(plug5.getInput())) {
return outputFromScoket;
}
/*
* Else, override the value by adapterOutput
*/
else {
String adapterOutput = plug5.getInput();
return adapterOutput;
}
}// End of class
This is how the Adapter pattern works. When one interface cannot be changed and has to be suited to the again cannot-be-changed client, an adapter is used so that both the interfaces can work together.
The adapter pattern takes two forms.
In the first form, a "class adapter" utilizes inheritance. The class adapter extends the adaptee class and adds the desired methods to the adapter. These methods can be declared in an interface(i.e the "Target" interface).
In the second form, an "object adapter" utilizes composition. The object adapter contains an adaptee & implements target interface to interact with adaptee.
Below example is from Sun Certified Enterprise Architect book:
package j2ee.architect.Adapter;
public class AdapterPattern {
public static void main(String[] args) {
System.out.println("Adapter Pattern Demonstration.");
System.out.println("------------------------------");
// Create targets.
System.out.println("Creating targets.");
TargetIF target1 = new AdapterByClass();
TargetIF target2 = new AdapterByObject();
// Call target requests
System.out.println("Calling targets.");
System.out.println("target1.newRequest()->"+target1.newRequest());
System.out.println("target2.newRequest()->"+target2.newRequest());
System.out.println();
}
}
package j2ee.architect.Adapter;
public class Adaptee {
public Adaptee() {
System.out.println("Adaptee constructed.");
}
public String oldRequest() {
return "Adaptee.oldRequest() called.";
}
}
package j2ee.architect.Adapter;
public class AdapterByClass extends Adaptee implements TargetIF {
public AdapterByClass() {
System.out.println("AdapterByClass constructed.");
}
public String newRequest() {
return oldRequest();
}
}
package j2ee.architect.Adapter;
public class AdapterByObject implements TargetIF {
private Adaptee adaptee;
public AdapterByObject() {
System.out.println("AdapterByObject constructed.");
}
public String newRequest() {
// Create an Adaptee object if it doesn't exist yet
if (adaptee == null) { adaptee = new Adaptee(); }
return adaptee.oldRequest();
}
}
package j2ee.architect.Adapter;
public interface TargetIF {
public String newRequest();
}
Example: In the EJB implementation model, we implement an EJB in a class that extends Session Bean or Entity Bean. We don't directly implement the EJBObject/home interfaces. EJB container generates a class that adapts the EJBobject Interface by forwarding the calls to the enterpise bean class & provides declarative transaction, persistence support.