0% found this document useful (0 votes)
78 views208 pages

Designpatternsinjava 171112205304 PDF

The document discusses design patterns in Java including the Factory, Abstract Factory, and Singleton patterns. It provides code examples of implementing each pattern. The Factory pattern allows defining a class to create objects of other classes without specifying the exact class. The Abstract Factory pattern provides an interface for creating families of related objects. The Singleton pattern ensures that only one instance of a class is created and provides a global access point to it.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
78 views208 pages

Designpatternsinjava 171112205304 PDF

The document discusses design patterns in Java including the Factory, Abstract Factory, and Singleton patterns. It provides code examples of implementing each pattern. The Factory pattern allows defining a class to create objects of other classes without specifying the exact class. The Abstract Factory pattern provides an interface for creating families of related objects. The Singleton pattern ensures that only one instance of a class is created and provides a global access point to it.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 208

DESIGN PATTERNS IN JAVA

Creational design patterns


FACTORY

DESIGN PATTERN
Usage of Factory
Design Pattern
When a class doesn't When a class wants When the parent
know what sub-classes that its sub-classes classes choose the
will be required to specify the objects creation of objects
create to be created. to its sub-classes.
Plan Abstract Class
1. import java.io.*;
2. abstract class Plan{
3. protected double rate;
4. abstract void getRate();
5.
6. public void calculateBill(int units){
7. System.out.println(units*rate);
8. }
9. }//end of Plan class.
Subclasses
1. class DomesticPlan extends Plan{ 1. class CommercialPlan extends 1. class InstitutionalPlan extends Plan{

2. //@override Plan{ 2. //@override

3. public void getRate(){ 2. //@override 3. public void getRate(){

4. rate=3.50; 3. public void getRate(){ 4. rate=5.50;

5. } 4. rate=7.50; 5. }

6. }//end of DomesticPlan class. 5. } 6. /end of InstitutionalPlan class.


1. class GetPlanFactory{

2. //use getPlan method to get object of type Plan

3. public Plan getPlan(String planType){

4. if(planType == null){

5. return null;

6. }

7. if(planType.equalsIgnoreCase("DOMESTICPLAN")) {

8. return new DomesticPlan();

9. }

10. else if(planType.equalsIgnoreCase("COMMERCIALPLAN")){

11. return new CommercialPlan();

12. }

13. else if(planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {

14. return new InstitutionalPlan();

15. }

16. return null;

17. }

18. }//end of GetPlanFactory class.


1. import java.io.*;

2. class GenerateBill{

3. public static void main(String args[])throws IOException{

4. GetPlanFactory planFactory = new GetPlanFactory();

5. System.out.print("Enter the name of plan for which the bill will be generated: ");

6. BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

7.

8. String planName=br.readLine();

9. System.out.print("Enter the number of units for bill will be calculated: ");

10. int units=Integer.parseInt(br.readLine());

11.

12. Plan p = planFactory.getPlan(planName);

13. //call getRate() method and calculateBill()method of DomesticPaln.

14. System.out.print("Bill amount for "+planName+" of "+units+" units is: ");

15. p.getRate();

16. p.calculateBill(units);

17. }

18. }//end of GenerateBill class.


Best Practices
JDBC is a good example for this pattern; application code
doesn’t need to know what database it will be used with, so
it doesn’t know what database-specific driver classes it
should use. Instead, it uses factory methods to get
Connections, Statements, and other objects to work with.
This gives flexibility to change the back-end database
without changing your DAO layer.
ABSTRACT FACTORY

DESIGN PATTERN
Intent
Provide an interface for creating families of related or dependent
objects without specifying their concrete classes.

Usage
● When a system should be independent of how its products are created,
composed, and represented.
● When a system should be configured with one of multiple families of
products.
● When a family of related product objects is designed to be used
together, and you need to enforce this constraint.
● When you want to provide a class library of products, and you want to
reveal just their interfaces, not their implementations.
WidgetFactory abstract class
public abstract class WidgetFactory{

public abstract Window createWindow();

public abstract ScrollBar createScrollBar();

public WidgetFactory getFactory(){

...

}
WidgetFactory imlpementing classes
public class PMWidgetFactory extends WidgetFactory{ public class MotifWidgetFactory extends WidgetFactory{

public Window createWindow(){ public Window createWindow(){

return new PMWindow(); return new MotifWindow();

}; };

public ScrollBar createScrollBar(){ public ScrollBar createScrollBar(){

return new PMScrollBar(); return new MotifScrollBar();

} }

} }
Window with its imlpementing classes
public abstract class Window{ public class MotifWindow extends Window{

public abstract void blaBlaBla(); public void blaBlaBla(){

} System.out.println(“Motif bla bla bla”)

public class PMWindow extends Window{

public void blaBlaBla(){

System.out.println(“PM bla bla bla”)

}
ScrollBar with its imlpementing classes
public abstract class ScrollBar{ public class MotifScrollBar extends ScrollBar{

public abstract void blaBlaBla(); public void blaBlaBla(){

} System.out.println(“Motif bla bla bla”)

public class PMScrollBar extends ScrollBar{

public void blaBlaBla(){

System.out.println(“PM bla bla bla”)

}
SINGLETON

DESIGN PATTERN
Singleton Pattern says that just "define a
class that has only one instance and provides a
global point of access to it".

In other words, a class must ensure that only


single instance should be created and single
object can be used by all other classes.

There are two forms of singleton design pattern

● Early Instantiation: creation of instance at


load time.

● Lazy Instantiation: creation of instance


when required.
Advantage of Singleton design pattern
● Saves memory because object is not created at each

request. Only single instance is reused again and

again.

Usage of Singleton design pattern


● Singleton pattern is mostly used in multi-threaded

and database applications. It is used in logging,

caching, thread pools, configuration settings etc.


To implement Singleton pattern, we have different approaches but all of them have
following common concepts.

● Private constructor to restrict


instantiation of the class from other
classes.
● Private static variable of the same class
that is the only instance of the class.
● Public static method that returns the
instance of the class, this is the global
access point for outer world to get the
instance of the singleton class.
Eager initialization public class EagerInitializedSingleton {

private static final EagerInitializedSingleton


In eager initialization, the instance = new EagerInitializedSingleton();
instance of Singleton Class
is created at the time of //private constructor to avoid client applications to
class loading, this is the use constructor
private EagerInitializedSingleton(){}
easiest method to create a
singleton class but it has a public static EagerInitializedSingleton
drawback that instance is getInstance(){
created even though client return instance;
}
application might not be
}
using it.
public class LazyInitializedSingleton {
Lazy Initialization
private static LazyInitializedSingleton instance;

private LazyInitializedSingleton(){} Lazy initialization method to


implement Singleton pattern
public static LazyInitializedSingleton
getInstance(){
creates the instance in the
if(instance == null){ global access method. Here
instance = new LazyInitializedSingleton(); is the sample code for
}
return instance; creating Singleton class with
} this approach.
}
Static block
public class StaticBlockSingleton {

initialization
private static StaticBlockSingleton instance;

private StaticBlockSingleton(){}

Static block initialization //static block initialization for exception handling


implementation is similar static{
try{
to eager initialization, instance = new StaticBlockSingleton();
except that instance of }catch(Exception e){
throw new RuntimeException("Exception occured in creating
class is created in the singleton instance");
static block that provides }
}
option for exception
handling. public static StaticBlockSingleton getInstance(){
return instance;
}
}
The easier way to create a thread-safe singleton
Thread Safe Singleton class is to make the global access method
synchronized, so that only one thread can execute
public class ThreadSafeSingleton { this method at a time.

private static ThreadSafeSingleton instance; public static ThreadSafeSingleton


getInstanceUsingDoubleLocking(){
private ThreadSafeSingleton(){} if(instance == null){
synchronized (ThreadSafeSingleton.class) {
public static synchronized ThreadSafeSingleton if(instance == null){
getInstance(){ instance = new ThreadSafeSingleton();
if(instance == null){ }
instance = new ThreadSafeSingleton(); }
} }
return instance; return instance;
} }

}
Bill Pugh Singleton Implementation
public class BillPughSingleton {

Bill Pugh came up with a private BillPughSingleton(){}


different approach to
private static class SingletonHelper{
create the Singleton class
private static final BillPughSingleton INSTANCE = new
using a inner static helper BillPughSingleton();
class. The Bill Pugh }
Singleton implementation
goes like this public static BillPughSingleton getInstance(){
return SingletonHelper.INSTANCE;
}
}
PROTOTYPE

DESIGN PATTERN
Concept
● GoF Definition: Specify the kinds of objects to create
using a prototypical instance, and create new objects
by copying this prototype.
● The prototype pattern provides an alternative method
for instantiating new objects by copying or cloning an
instance of an existing one. Creating a new instance,
in a real-world scenario, is normally treated as an
expensive operation.
Examples
● Suppose we have a master copy of a valuable document.
We want to make some change to it to get a different
feel. We can make a photocopy of this document and then
try to edit our changes.
● Suppose we have made an application. The next time we
want to create a similar application with somesmall
changes, we must start with a copy from our master copy
application and make the changes. We’ll not start from
the scratch.
BaseCar.class
public abstract class BasicCar implements Cloneable{
public String modelname;
public int price;
public String getModelname(){
return modelname;
}
public void setModelname(String modelname){
this.modelname = modelname;
}
public static int setPrice(){
int price = 0;
Random r = new Random();
int p = r.nextInt(100000);
price = p;
return price;
}
public BasicCar clone() throws CloneNotSupportedException{
return (BasicCar)super.clone();
}
}
Ford.class & Nano.class
public class Ford extends BasicCar public class Nano extends BasicCar{
{ public Nano(String m){
public Ford(String m){ modelname = m;
modelname = m; }
} @Override
@Override public BasicCar clone() throws
public BasicCar clone() throws CloneNotSupportedException{
CloneNotSupportedException{ return (Nano)super.clone();
return (Ford)super.clone(); }
} }
}
PrototypePatternEx.class
public class PrototypePatternEx{
public static void main(String[] args) throws CloneNotSupportedException{
System.out.println("***Prototype Pattern Demo***\n");
BasicCar nano_base = new Nano("Green Nano");
nano_base.price=100000;
BasicCar ford_basic = new Ford("Ford Yellow");
ford_basic.price=500000;
BasicCar bc1;
//Clone Nano Object
bc1 =nano_base.clone();
//Price will be more than 100000 for sure
bc1.price = nano_base.price+BasicCar.setPrice();
System.out.println("Car is: "+ bc1.modelname+" and it's price is Rs."+bc1.price);
//Clone Ford Object
bc1 =ford_basic.clone();
//Price will be more than 500000 for sure
bc1.price = ford_basic.price+BasicCar.setPrice();
System.out.println("Car is: "+ bc1.modelname+" and it's price is Rs."+bc1.price);
}
}
WHEN TO USE
● When the system does not care about the creational
mechanism of the products,this pattern is very helpful.
● We can use this pattern when we need to instantiate
classes at runtime.
● In our example, we have used the default clone() method
in Java, which is a shallow copy. Thus, it is
inexpensive compared to a deep copy.
What are the advantages of the prototype pattern?
● We can include or discard products at runtime.
● We can create new instances with a cheaper cost.
What are the disadvantages of the prototype pattern?
● Each subclass has to implement the cloning mechanism.
● Implementing the cloning mechanism can be challenging
if the objects under consideration do not support
copying or if there is any kind of circular reference.
BUILDER

DESIGN PATTERN
Builder Pattern says that "construct a complex object from simple objects using
step-by-step approach"

It is mostly used when object can't be created in single step like in the de-serialization of a complex object.

Advantage of Builder Design Pattern

The main advantages of Builder Pattern are as follows:

● It provides clear separation between the construction and representation of an object.

● It provides better control over construction process.

● It supports to change the internal representation of objects.


Create Packing interface Create 2 abstract classes CD and Company
1. public interface Packing {
1. public abstract class CD implements Packing{
2. public String pack();
2. public abstract String pack();
3. public int price();
3. }
4. }

1. public abstract class Company extends CD{

2. public abstract int price();

3. }
Create 2 implementation classes of Company: Sony and Samsung

1. public class Sony extends Company{


1. public class Samsung extends Company {
2. @Override
2. @Override
3. public int price(){
3. public int price(){
4. return 20;
4. return 15;
5. }
5. }
6. @Override
6. @Override
7. public String pack(){
7. public String pack(){
8. return "Sony CD";
8. return "Samsung CD";
9. }
9. }
10. }
10. }
Create the CDType class

import java.util.ArrayList; public void showItems(){

import java.util.List; for (Packing packing : items){

public class CDType { System.out.print("CD name : "+packing.pack());

private List<Packing> items=new System.out.println(", Price : "+packing.price());

ArrayList<Packing>(); }

public void addItem(Packing packs) { }

items.add(packs); }//End of the CDType class.

public void getCost(){

for (Packing packs : items) {

packs.price();

}
Create the CDBuilder class Create the BuilderDemo class

1. public class CDBuilder { 1. public class BuilderDemo{

2. public CDType buildSonyCD(){ 2. public static void main(String args[]){

3. CDType cds=new CDType(); 3. CDBuilder cdBuilder=new CDBuilder();

4. cds.addItem(new Sony()); 4. CDType cdType1=cdBuilder.buildSonyCD();

5. return cds; 5. cdType1.showItems();

6. } 6.

7. public CDType buildSamsungCD(){ 7. CDType cdType2=cdBuilder.buildSamsungCD();

8. CDType cds=new CDType(); 8. cdType2.showItems();

9. cds.addItem(new Samsung()); 9. }

10. return cds; 10. }

11. }

12. }
let’s assume, our User object has following 5 attributes i.e. firstName, lastName, age, phone and address.

In normal practice, if you want to make a immutable User class, then you must pass all five information as parameters to
constructor. It will look like this:

public User (String firstName, String lastName, int age, String phone, String address){

this.firstName = firstName;

this.lastName = lastName;

this.age = age;

this.phone = phone;

this.address = address;

}
Very good. Now what if only firstName and lastName are mandatory and rest 3 fields are optional. Problem !! We need more
constructors.

public User (String firstName, String lastName, int age, String phone){ ... }

public User (String firstName, String lastName, String phone, String address){ ... }

public User (String firstName, String lastName, int age){ ... }

public User (String firstName, String lastName){ ... }

We will need some more like above. Still can manage? Now let’s introduce our sixth attribute i.e. salary. Now it is problem.

One way it to create more constructors, and another is to loose the immutability and introduce setter methods. You choose any of
both options, you loose something, right?

Here, builder pattern will help you to consume additional attributes while retaining the immutability of Use class.
//All getter, and NO setter to provde immutability
public class User
public String getFirstName() {
{ return firstName;
//All final attributes }
public String getLastName() {
private final String firstName; // required
return lastName;
private final String lastName; // required }
private final int age; // optional public int getAge() {
return age;
private final String phone; // optional
}
private final String address; // optional public String getPhone() {
return phone;
}
private User(UserBuilder builder) { public String getAddress() {
this.firstName = builder.firstName; return address;
this.lastName = builder.lastName; }

this.age = builder.age; @Override


this.phone = builder.phone; public String toString() {
this.address = builder.address; return "User: "+this.firstName+",
"+this.lastName+", "+this.age+", "+this.phone+",
} "+this.address;
}
public static class UserBuilder //Return the finally consrcuted User object
{ public User build() {
User user = new User(this);
private final String firstName; validateUserObject(user);
private final String lastName; return user;
private int age; }
private void validateUserObject(User user) {
private String phone; //Do some basic validations to check
private String address; //if user object does not break any
assumption of system
}
public UserBuilder(String firstName, }
String lastName) { }
this.firstName = firstName;
this.lastName = lastName; public static void main(String[] args) {
User user1 = new User.UserBuilder("Name",
}
"LastName")
.age(30)
public UserBuilder address(String address) { .phone("1234567")
this.address = address; .address(" address 1234")
.build();
return this;
} System.out.println(user1);
}
OBJECT POOL

DESIGN PATTERN
Mostly, performance is the key issue during the software development and the object creation, which
may be a costly step.

Object Pool Pattern says that " to reuse the object that are expensive to create".

Basically, an Object pool is a container which contains a specified amount of objects. When an object is
taken from the pool, it is not available in the pool until it is put back. Objects in the pool have a
lifecycle: creation, validation and destroy.

A pool helps to manage available resources in a better way. There are many using examples: especially
in application servers there are data source pools, thread pools etc.
Advantage of Object Pool design pattern
● It boosts the performance of the application significantly.

● It is most effective in a situation where the rate of initializing a class instance is high.

● It manages the connections and provides a way to reuse and share them.

● It can also provide the limit for the maximum number of objects that can be created.

Usage:
● When an application requires objects which are expensive to create. Eg: there is a need of opening too

many connections for the database then it takes too longer to create a new one and the database server

will be overloaded.

● When there are several clients who need the same resource at different times.

NOTE: Object pool design pattern is essentially used in Web Container of the server for creating thread pools and data source
pools to process the requests.
Object pool
public abstract class ObjectPool<T> {
private Set<T> available = new HashSet<>();
private Set<T> inUse = new HashSet<>();
protected abstract T create();

/**
* Checkout object from pool
*/
public synchronized T checkOut() {
if (available.isEmpty()) {
available.add(create());
}
T instance = available.iterator().next();
available.remove(instance);
inUse.add(instance);
return instance;
}
public class Oliphaunt {
public synchronized void checkIn(T instance) {
private static int counter = 1;
inUse.remove(instance);
private final int id;
available.add(instance);
}
public Oliphaunt() {
id = counter++;
try {
@Override
Thread.sleep(1000);
public synchronized String toString() {
} catch (InterruptedException e) {
return String.format("Pool available=%d inUse=%d",
e.printStackTrace();
available.size(), inUse.size());
}
}
}
}
public int getId() {
return id;
}
@Override
public String toString() {
return String.format("Oliphaunt id=%d", id);
}
}
public class App {
public class OliphauntPool extends ObjectPool<Oliphaunt> { public static void main(String[] args) {
OliphauntPool pool = new OliphauntPool();
LOGGER.info(pool.toString());
@Override Oliphaunt oliphaunt1 = pool.checkOut();
LOGGER.info("Checked out {}", oliphaunt1);
protected Oliphaunt create() {
LOGGER.info(pool.toString());
return new Oliphaunt();
Oliphaunt oliphaunt2 = pool.checkOut();
} LOGGER.info("Checked out {}", oliphaunt2);
} Oliphaunt oliphaunt3 = pool.checkOut();
LOGGER.info("Checked out {}", oliphaunt3);
LOGGER.info(pool.toString());
LOGGER.info("Checking in {}", oliphaunt1);
pool.checkIn(oliphaunt1);
LOGGER.info("Checking in {}", oliphaunt2);
pool.checkIn(oliphaunt2);
LOGGER.info(pool.toString());
Oliphaunt oliphaunt4 = pool.checkOut();
LOGGER.info("Checked out {}", oliphaunt4);
Oliphaunt oliphaunt5 = pool.checkOut();
LOGGER.info("Checked out {}", oliphaunt5);
LOGGER.info(pool.toString());
}
}
Structural design patterns
ADAPTER

DESIGN PATTERN
Adapter(Wrapper)
An Adapter Pattern says that just "converts the interface of a class into another interface that a
client wants"

Advantage of Adapter Pattern


● It allows two or more previously incompatible objects to interact.

● It allows reusability of existing functionality.

Usage of Adapter pattern


● When an object needs to utilize an existing class with an incompatible interface.

● When you want to create a reusable class that cooperates with classes which don't have compatible
interfaces
● When you want to create a reusable class that cooperates with classes which don't have compatible

interfaces.
UML for Adapter pattern
● Target Interface: This is the desired interface class which will be used by the clients.
● Adapter class: This class is a wrapper class which implements the desired target interface and modifies the
specific request available from the Adaptee class.
● Adaptee class: This is the class which is used by the Adapter class to reuse the existing functionality and modify
them for desired use.
● Client: This class will interact with the Adapter class.

public class AdapterPatternDemo {

public static void main(String args[]){

CreditCard targetInterface=new BankCustomer();

targetInterface.giveBankDetails();

System.out.print(targetInterface.getCreditCard());

}
BRIDGE

DESIGN PATTERN
Bridge

Decouple an abstraction from its implementation so that the two can vary independently

The Abstraction defines the abstraction, and


maintains the reference to the implementor.
RefinedAbstraction provides an extension to
the Abstraction, usually adding extra methods
that provide different ways of getting at the
same functionality. The Implementor interface
defines an interface for the implementation
classes (the ConcreateImplementor classes).
The Bridge Pattern is also known as Handle or Body.

Advantage of Bridge Pattern


● It enables the separation of implementation from the interface.

● It improves the extensibility.

● It allows the hiding of implementation details from the client.

Usage of Bridge Pattern


● When you don't want a permanent binding between the functional abstraction and its implementation.

● When both the functional abstraction and its implementation need to extended using sub-classes.

● It is mostly used in those places where changes are made in the implementation does not affect the clients.
First, we have our TV implementation //Concrete Implementor
interface: public class Sony implements TV {

//Implementor void on() {


// Sony specific on
public interface TV{ }
public void on();
public void off(); public void off() {
public void tuneChannel(int channel); // Sony specific off
} }

public void tuneChannel(int channel) {


// Sony specific tuneChannel
And then we create two specific }
implementations - one for Sony and one }
for Philips:
//Concrete Implementor Now, we create a remote control abstraction to
public class Philips implements TV { control the TV:

public void on() { //Abstraction


// Philips specific on public abstract class RemoteControl {
} private TV implementor;
public void off() {
public void on() {
// Philips specific off
implementor.on();
}
}
public void tuneChannel(int channel) {
// Philips specific tuneChannel public void off() {
} implementor.off();
}
}
public void setChannel(int channel) {

implementor.tuneChannel(channel);
}
}
As the remote control holds a reference to the TV, it can delegates the methods through to the interface. But
what is we want a more specific remote control - one that has the + / - buttons for moving through the
channels? All we need to do is extend our RemoteControl abstraction to contain these concepts:

public class ConcreteRemote extends RemoteControl {


private int currentChannel;

public void nextChannel() {


currentChannel++;
setChannel(currentChannel);
}

public void prevChannel() {


currentChannel--;
setChannel(currentChannel);
}
}
public interface Color {
public abstract class Shape {
public void applyColor(); //Composition - implementor
} protected Color color;

//constructor with implementor as input


argument
public class Triangle extends Shape{
public Shape(Color c){
this.color=c;
public Triangle(Color c) {
}
super(c);
}
abstract public void applyColor();
}
@Override
public void applyColor() {
System.out.print("Triangle filled
with color ");
color.applyColor();
}

}
public class Pentagon extends Shape{
public class RedColor implements Color{

public Pentagon(Color c) {
public void applyColor(){
super(c);
System.out.println("red.");
}
}
}
@Override
public void applyColor() {
System.out.print("Pentagon
filled with color ");
public class GreenColor implements
color.applyColor();
Color{
}

public void applyColor(){


}
System.out.println("green.");
}
}
public class BridgePatternTest {

public static void main(String[] args) {


Shape tri = new Triangle(new RedColor());
tri.applyColor();

Shape pent = new Pentagon(new GreenColor());


pent.applyColor();
}

}
COMPOSITE

DESIGN PATTERN
Advantage of Composite Design Pattern
A Composite Pattern says that just "allow clients to
operate in generic manner on objects that may
or may not represent a hierarchy of objects".
● It defines class hierarchies that contain primitive and complex objects.

● It makes easier to you to add new kinds of components.

● It provides flexibility of structure with manageable class or interface.


Usage of Composite Pattern
● When you want to represent a full or partial hierarchy of objects.

● When the responsibilities are needed to be added dynamically to

the individual objects without affecting other objects. Where the

responsibility of object may vary from time to time.


UML for Composite Pattern
4 Elements used in Composite Pattern
1) Component
● Declares interface for objects in composition.

● Implements default behavior for the interface common to all classes as appropriate.

● Declares an interface for accessing and managing its child components.

2) Leaf
● Represents leaf objects in composition. A leaf has no children.

● Defines behavior for primitive objects in the composition.


4 Elements used in Composite Pattern
3) Composite
● Defines behavior for components having children.

● Stores child component.

● Implements child related operations in the component interface.

4) Client
● Manipulates objects in the composition through the component interface.
Example

public interface Shape {


public void draw(String fillColor);
}

public class Triangle implements Shape {

@Override
public void draw(String fillColor) {
System.out.println("Drawing Triangle with color "+fillColor);
}

}
Example

public class Circle implements Shape {

@Override
public void draw(String fillColor) {
System.out.println("Drawing Circle with color "+fillColor);
}

}
Example
//adding shape to drawing
public void add(Shape s){
this.shapes.add(s);
}

public class Drawing implements Shape{ //removing shape from drawing


public void remove(Shape s){
//collection of Shapes shapes.remove(s);
private List<Shape> shapes = new }
ArrayList<Shape>();
//removing all the shapes
@Override public void clear(){
public void draw(String fillColor) { System.out.println("Clearing all the
for(Shape sh : shapes) shapes from drawing");
{ this.shapes.clear();
sh.draw(fillColor); }
} }
}
Example

public class TestCompositePattern { drawing.draw("Red");

public static void main(String[] args) { drawing.clear();


Shape tri = new Triangle();
Shape tri1 = new Triangle(); drawing.add(tri);
Shape cir = new Circle(); drawing.add(cir);
drawing.draw("Green");
Drawing drawing = new Drawing(); }
drawing.add(tri1);
drawing.add(tri1); }
drawing.add(cir);
Output

Drawing Triangle with color Red


Drawing Triangle with color Red
Drawing Circle with color Red
Clearing all the shapes from drawing
Drawing Triangle with color Green
Drawing Circle with color Green
Composite Pattern Important Points

● Composite pattern should be applied only when the group of objects


should behave as the single object.
● Composite design pattern can be used to create a tree like structure.
4 Elements used in Composite Pattern
3) Composite
● Defines behavior for components having children.

● Stores child component.

● Implements child related operations in the component interface.

4) Client
● Manipulates objects in the composition through the component interface.
DECORATE

DESIGN PATTERN
Concept
● GoF Definition: Attach additional responsibilities to an object dynamically.Decorators

provide a flexible alternative to subclassing for extending functionality.

● This main principle of this pattern says that we cannot modify existing functionalities

but we can extend them. In other words, this pattern is open for extension but closed

for modification.

● The core concept applies when we want to add some specific functionalities to some

specific object instead of to the whole class.


Real-Life Example
Suppose you already own a house. Now you have decided to
add an additional floor. Obviously, you do not want to
change the architecture of ground floor (or existing
floors). You may want to change the design of the
architecture for the newly added floor without affecting
the existing architecture for existing floor(s).
class ConcreteDecoratorEx_1 extends AbstractDecorator{
abstract class Component{
public void doJob(){
public abstract void doJob();
super.doJob();
}
//Add additional thing if necessary
System.out.println("I am explicitly from Ex_1");
}}
class ConcreteComponent extends Component class ConcreteDecoratorEx_2 extends AbstractDecorator{
{ public void doJob(){
@Override System.out.println("");
public void doJob(){ System.out.println("***START Ex-2***");
System.out.println(" I am from super.doJob();
Concrete Component-I am closed //Add additional thing if necessary
for modification."); System.out.println("Explicitly From
} DecoratorEx_2");
} System.out.println("***END. EX-2***");
}}
public static void main(String[] args){
abstract class AbstractDecorator extends Component{ System.out.println("***Decorator pattern Demo***");
protected Component com ; ConcreteComponent cc = new ConcreteComponent();
public void SetTheComponent(Component c){
com = c; ConcreteDecoratorEx_1 cd_1 = new ConcreteDecoratorEx_1();
} // Decorating ConcreteComponent Object //cc with
public void doJob(){ ConcreteDecoratorEx_1
if (com != null){ cd_1.SetTheComponent(cc);
com.doJob(); cd_1.doJob();
} ConcreteDecoratorEx_2 cd_2= new ConcreteDecoratorEx_2();
} cd_2.SetTheComponent(cd_1);
} cd_2.doJob();
}}
Advantages
● Without disturbing existing objects in the system, we can add new
functionality to a particular object.
● Allows to modify object dynamically
● It is more flexible than inheritance
● Simplifies code, as you add new functionality using many simple classes
● We can code incrementally. Rather than rewrite old code you can extend
with new code
Different from inheritance
● We can add or remove responsibilities by simply
attaching or detaching decorators. But with the simple
inheritance technique, we need to create a new class
for new responsibilities.
● First of all, if we are careful enough, there is no
significant disadvantage. But if we create too many
decorators in the system, the system will be hard to
maintain and debug.
Usage
You would use it when you need capabilities of inheritance
with subclasses, but you need add functionality at runtime.
FACADE

DESIGN PATTERN
Concept
● GoF Definition: Provide a unified interface to a set of interfaces in a system. Facade
defines a higher-level interface that makes the subsystem easier to use.

● Fasade emphasize the abstraction and hide the complex details by exposing a simple
interface.
Examples
● Suppose you are going to organize a birthday party and you have invited 100 people.
Nowadays, you can go to any party organizer and let him/her know the minimum
information— (party type, date and time of the party, number of attendees, etc.). The
organizer will do the rest for you. You do not even think about how he will decorate the
party room, whether people will take food from self-help counter or will be served by a
caterer, and so on.

● We can think about a case where we use a method from a library. The user doesn’t care
how the method is implemented in the library. He/she just calls the method to serve
his/her easy purpose. The pattern can be best described by the example that follows.
public class RobotBody{ public class RobotFacade{
RobotColor rc;
public void CreateBody(){
RobotMetal rm ;
System.out.println("Body RobotBody rb;
Creation done"); public RobotFacade(){
}} rc = new RobotColor();
rm = new RobotMetal();
public class RobotColor{
rb = new RobotBody();
private String color;
}
public void SetColor(String color){
public void ConstructRobot(String color,String metal){
this.color = color;
System.out.println("\nCreation of the Robot
System.out.println("Color is set to : Start");
"+ this.color);
rc.SetColor(color);
}
rm.SetMetal(metal);
}
rb.CreateBody();
System.out.println(" \nRobot Creation End");
public class RobotMetal{ System.out.println();
private String metal; }}
public void SetMetal(String metal){ class FacadePatternEx{
this.metal=metal; public static void main(String[] args){
System.out.println("Metal is set to : System.out.println("***Facade Pattern Demo***");
"+this.metal); RobotFacade rf1 = new RobotFacade();
} rf1.ConstructRobot("Green", "Iron");
} RobotFacade rf2 = new RobotFacade();
rf2.ConstructRobot("Blue", "Steel");
}
}
Note
● We use Facade pattern to represent a simple interface instead of a complex subsystem.
● Here we promote weak coupling among subsystems—so, in this way, we are making them
portable.
● We already mentioned that we separate subsystems from clients by a simple interface.
With this model, we not only make the system easier to use but also reduce the number of
objects that the clients need to deal with.
● There is truly no major disadvantage associated with this pattern. On the other hand, it
has proven its usefulness in libraries like jQuery also.
FLYWEIGHT

DESIGN PATTERN
Flyweight pattern is primarily used to reduce the number of objects created and to decrease memory footprint and increase
performance.Flyweight pattern tries to reuse already existing similar kind objects by storing them and creates new object
when no matching object is found

Before we apply flyweight design pattern, we need to consider following factors:

● The number of Objects to be created by application should be huge.


● The object creation is heavy on memory and it can be time consuming too.
● The object properties can be divided into intrinsic and extrinsic properties, extrinsic properties of an Object should be
defined by the client program.

Intrinsic properties make the Object unique.


The flyweight factory will be used by client programs to instantiate the Object, so we need to keep a map
of Objects in the factory that should not be accessible by client application.

Flyweight Design Pattern Example in JDK


All the wrapper classes valueOf() method uses cached objects showing use of Flyweight design pattern.
The best example is Java String class String Pool implementation.

Flyweight Design Pattern Important Points

● Flyweight pattern introduces complexity and if number of shared objects are huge then there is a
trade of between memory and time, so we need to use it judiciously based on our requirements.
● Flyweight pattern implementation is not useful when the number of intrinsic properties of Object is
huge.
public interface Shape { public class ShapeFactory {
void draw(); private static final HashMap<String, Shape> circleMap =
} new HashMap();

public class Circle implements Shape { public static Shape getCircle(String color) {
private String color; Circle circle = (Circle)circleMap.get(color);
private int x;
private int y; if(circle == null) {
private int radius; circle = new Circle(color);
public Circle(String color){ circleMap.put(color, circle);
this.color = color; System.out.println("Creating circle of color : " +
} color);
public void setX(int x) { }
this.x = x; return circle;
} }
public void setY(int y) { }
this.y = y;
} public class FlyweightPatternDemo {
public void setRadius(int radius) { private static final String colors[] = { "Red", "Green",
this.radius = radius; "Blue", "White", "Black" };
} public static void main(String[] args) {
@Override for(int i=0; i < 20; ++i) {
public void draw() { Circle circle =
System.out.println("Circle: Draw() [Color : (Circle)ShapeFactory.getCircle(getRandomColor());
" + color + ", x : " + x + ", y :" + y + ", radius circle.setX(getRandomX());
:" + radius); circle.setY(getRandomY());
} circle.setRadius(100);
} circle.draw();
} }
}
PROXY

DESIGN PATTERN
Concept
Proxy pattern intent is to “Provide a surrogate or
placeholder for another object to control access to
it”.

Let’s say we have a class that can run some command


on the system. Now if we are using it, its fine but
if we want to give this program to a client
application, it can have severe issues because
client program can issue command to delete some
system files or change some settings that you don’t
want.
Advantage and Usage of Proxy Pattern
Advantage
● It provides the protection to the original object from the outside world.

Usage
● It can be used in Virtual Proxy scenario---Consider a situation where there is

multiple database call to extract huge size image.

● It can be used in Protective Proxy scenario---It acts as an authorization layer to

verify that whether the actual user has access the appropriate content or not.

● It can be used in Remote Proxy scenario---A remote proxy can be thought about the stub

in the RPC call.

● It can be used in Smart Proxy scenario---A smart proxy provides additional layer of

security by interposing specific actions when the object is accessed.


UML for Proxy Pattern:
Example of Proxy Pattern
public class CommandExecutorProxy implements CommandExecutor {
private boolean isAdmin;
private CommandExecutor executor;
public interface CommandExecutor { public CommandExecutorProxy(String user, String pwd){
public void runCommand(String cmd) throws Exception; if("Pankaj".equals(user) && "J@urnalD$v".equals(pwd))
} isAdmin=true;
executor = new CommandExecutorImpl();
public class CommandExecutorImpl implements CommandExecutor { }
@Override
@Override public void runCommand(String cmd) throws Exception {
public void runCommand(String cmd) throws IOException { if(isAdmin){
//some heavy implementation executor.runCommand(cmd);
Runtime.getRuntime().exec(cmd); }else{
System.out.println("'" + cmd + "' command executed."); if(cmd.trim().startsWith("rm")){
} throw new Exception("rm command is not
allowed for non-admin users.");
} }else{
executor.runCommand(cmd);
}
}
}
}
public class ProxyPatternTest {

public static void main(String[] args){


CommandExecutor executor = new CommandExecutorProxy("Pankaj",
"wrong_pwd");
try {
executor.runCommand("ls -ltr");
executor.runCommand(" rm -rf abc.pdf");
} catch (Exception e) {
System.out.println("Exception Message::"+e.getMessage());
}

}
OutPut

1. 'ls -ltr' command executed.

2. Exception Message::rm command is not allowed for non-admin users.

Proxy Pattern Examples in JDK

Package java.rmi
Behavioral Design Patterns
CHAIN OF RESPONSIBILITY

DESIGN PATTERN
Chain Of Responsibility Pattern
In chain of responsibility, sender sends a request to a chain of objects.
The request can be handled by any object in the chain.

● A Chain of Responsibility Pattern says that just "avoid coupling


the sender of a request to its receiver by giving multiple
objects a chance to handle the request". For example, an ATM
uses the Chain of Responsibility design pattern in money giving
process.

In other words, we can say that normally each receiver contains


reference of another receiver. If one object cannot handle the request
then it passes the same to the next receiver and so on.
Advantage and Usage of Chain of Responsibility Pattern

Advantage

● It reduces the coupling.


● It adds flexibility while assigning the responsibilities to objects.
● It allows a set of classes to act as one; events produced in one class can
be sent to other handler classes with the help of composition.

Usage

● When more than one object can handle a request and the handler is unknown.
● When the group of objects that can handle the request must be specified in
dynamic way.
UML for Chain of Responsibility Pattern:
Example of Chain of Responsibility Pattern
class Money { abstract class NoteModule{
private int amt;
protected NoteModule next;
public Money(int amt) { abstract void takeMoney(Money money);
setAmt(amt) public void setNextMoneyModule(NoteModule next) {
} this.next = next;
}
public int getAmt() {
return amt; }
}

public void setAmt(int amt) { class Note{


if(amt> 0 && amt<=200_000 &&
amt%Note.AMD1000==0){ public static final int AMD1000 = 1000;
this.amt = amt; public static final int AMD5000 = 5000;
public static final int AMD10000 = 10000;
}else{
public static final int AMD20000 = 20000;
throw new RuntimeException("Error");
}} }
}
class NoteModule1000 extends NoteModule{ class NoteModule5000 extends NoteModule{

@Override @Override

void takeMoney(Money money) { void takeMoney(Money money) {

int countNote = money.getAmt()/Note.AMD1000; int countNote = money.getAmt()/Note.AMD5000;

int remind = money.getAmt()%Note.AMD1000; int remind = money.getAmt()%Note.AMD5000;

if(countNote > 0){ if(countNote > 0){

System.out.println(countNote + " - " + System.out.println(countNote + " - " +


Note.AMD1000); Note.AMD5000);

} }

if(remind > 0 && next != null){ if(remind > 0 && next != null){

next.takeMoney(new Money(remind)); next.takeMoney(new Money(remind));

} }

} }

} }
class NoteModule10000 extends NoteModule{ class NoteModule20000 extends NoteModule{

@Override @Override

void takeMoney(Money money) { void takeMoney(Money money) {

int countNote = money.getAmt()/Note.AMD10000; int countNote = money.getAmt()/Note.AMD20000;

int remind = money.getAmt()%Note.AMD10000; int remind = money.getAmt()%Note.AMD20000;

if(countNote > 0){ if(countNote > 0){

System.out.println(countNote + " - " + System.out.println(countNote + " - " +


Note.AMD10000); Note.AMD20000);

} }

if(remind > 0 && next != null){ if(remind > 0 && next != null){

next.takeMoney(new Money(remind)); next.takeMoney(new Money(remind));

} } } }

} }
public class BankomatApp {

public static void main(String[] args) {

NoteModule note1000 = new NoteModule1000();

NoteModule note5000 = new NoteModule5000();

NoteModule note10000 = new NoteModule10000();

NoteModule note20000 = new NoteModule20000();

note20000.setNextMoneyModule(note10000);

note10000.setNextMoneyModule(note5000);

note5000.setNextMoneyModule(note1000);

note20000.takeMoney(new Money(117_000));

}
OutPut

117_000 117_100

5 - 20000 Error

1 - 10000

1 - 5000

2 - 1000
Chain of Responsibility Pattern Examples in JDK

● java.util.logging.Logger#log()
● javax.servlet.Filter#doFilter()
Pitfalls

● Handling/handler guarantee
● Runtime configuration risk
● Chain length performance issues
Chain of Responsibility Summary

● Decoupling sender and receiver


● Runtime configuration
● Hierarchical in nature
● Careful with large chain
COMMAND

DESIGN PATTERN
Command pattern is a data driven design pattern and falls
under behavioral pattern category.

A Command Pattern says that "encapsulate a request under an object as a command and pass it to invoker

object. Invoker object looks for the appropriate object which can handle this command and pass the

command to the corresponding object and that object executes the command".

It is also known as Action or Transaction .

Advantage of command pattern

● It separates the object that invokes the operation from the object that actually performs the operation
● It makes easy to add new commands, because existing classes remain unchanged.
Usage of command pattern
● A history of requests is needed.
● You need callback functionality.
● Requests need to be handled at variant times or in variant orders.
● The invoker should be decoupled from the object handling the invocation.

Command in the Real World


One example of the command pattern being executed in the real world is the idea of a table
order at a restaurant: the waiter takes the order, which is a command from the customer.
This order is then queued for the kitchen staff. The waiter tells the chef that the a new order
has come in, and the chef has enough information to cook the meal.
Sequence class diagram
Command declares an interface for all commands, providing a simple execute() method which
asks the Receiver of the command to carry out an operation. The Receiver has the knowledge of what
to do to carry out the request. The Invoker holds a command and can get the Command to execute a
request by calling the execute method. The Client creates ConcreteCommands and sets a Receiver
for the command. The ConcreteCommand defines a binding between the action and the receiver.
When the Invoker calls execute the ConcreteCommand will run one or more actions on the Receiver.
Let's use a remote control as the example. Our remote is the center of home automation and can control
everything. We'll just use a light as an example, that we can switch on or off, but we could add many more
commands.

//Command
public interface Command{
public void execute();
}

//Concrete Command
//Concrete Command
public class LightOffCommand implements
public class LightOnCommand implements
Command{
Command{
//reference to the light
//reference to the light
Light light;
Light light;
public LightOffCommand(Light light){
public LightOnCommand(Light light){
this.light = light;
this.light = light;
}
}
public void execute(){
public void execute(){
light.switchOff();
light.switchOn();
}
}
}
}
//Receiver
public class Light{ //Client
private boolean on; public class Client{
public void switchOn(){ public static void main(String[] args) {
on = true; RemoteControl control = new RemoteControl();
} Light light = new Light();
public void switchOff(){ Command lightsOn = new LightsOnCommand(light);
on = false; Command lightsOff = new LightsOffCommand(light);
} //switch on
} control.setCommand(lightsOn);
control.pressButton();
//Invoker
//switch off
public class RemoteControl{
control.setCommand(lightsOff);
private Command command;
control.pressButton();
public void setCommand(Command command){
}
this.command = command;
}
}
public void pressButton(){
command.execute();
}
}
Watch Out for the Downsides

This pattern ends up forcing a lot of Command classes that will make your design look cluttered -
more operations being made possible leads to more command classes. Intelligence required of
which Command to use and when leads to possible maintenance issues for the central controller.
INTERPRETER

DESIGN PATTERN
Definition: Given a language, define a representation for its grammar along with an
interpreter that uses the representation to interpret sentences in the language.
Concept

Here, in general, we define a grammatical representation for a language and provide an


interpreter to deal with that grammar (e.g., in our example we have interpreted a string
input as binary data). In simple words, this pattern says how to evaluate sentences in a
language.

Real–Life Example

A language translator who translates a language for us provides a classic example for this
pattern. Or, we can also consider music notes as our grammar and musicians as our
interpreters.

Computer World Example

A Java compiler interprets the source code into bytecode. This byte code is understandable
by JVM (Java virtual machine). In C# also, our source code is converted to MSIL (Microsoft
intermediate language) code, which is interpreted by CLR (common language runtime). Upon
execution, this MSIL (intermediate code) is converted to native code (binary executable
code) by a JIT (Just In time) compiler.
Implementation

package interpreter.pattern.demo; interface IExpression


import java.util.Scanner; {
/*Context class: interpretation is carried out based on our implementation.*/ void interpret(Context ic);
}

class Context{
public String input; class StringToBinayExp implements IExpression {
public Context(String input){ private String str;
this.input=input;
} public StringToBinaryExp(String s) {
public void getBinaryForm(String input){ str = s;
int i = Integer.parseInt(input); }
//integer to its equivalent binary string representation
String binaryString = Integer.toBinaryString(i); @Override public void interpret(Context ic) {
System.out.println("Binary equivalent of "+input+ " is "+ binaryString); ic.getBinaryForm(str);
} }

}
public void printInWords(String input) {
this.input = input;
System.out.println("Printing the input in words:"); class IntToWords implements IExpression {
char c[]=input.toCharArray();
for(int i=0;i<c.length;i++){
switch (c[i]) private String str;
{ public IntToWords(String str) {
case '1': this.str = str;
System.out.print("One "); }
Break;
... @Override public void interpret(Context ic) {
case '0': ic.printInWords(str);
System.out.print("Zero "); }
break;
default:
System.out.print("* "); }
break;
}} }}
class InterpreterPatternEx {
public Context clientContext=null;
public IExpression exp=null;

public InterpreterPatternEx(Context c) {
clientContext = c;
}

public void interpret(String str) {


//We'll test 2 consecutive inputs at a time
for(int i=0;i<2;i++){
System.out.println("\nEnter ur choice(1 or 2)");
Scanner in = new Scanner(System.in);
String c = in.nextLine();
if (c.equals("1")) {
exp = new IntToWords(str);
exp.interpret(clientContext);
}
else {
exp = new StringToBinaryExp(str);
exp.interpret(clientContext);
}
}
}

public static void main(String[] args) {


System.out.println("\n***Interpreter Pattern Demo***\n");
System.out.println("Enter a number :");
Scanner in = new Scanner(System.in);
String input = in.nextLine();
Context context=new Context(input);
InterpreterPatternEx client = new InterpreterPatternEx(context);
client.interpret(input);
}
}
Note
1. This pattern is widely used to interpret the statements in a language as
abstract syntax trees. It performs best when the grammar is easy to
understand and simple.

2. We can represent, modify, or implement a grammar easily.

3. We can evaluate an expression in our preferred ways. It is up to us how


we’ll interpret those expressions.

4. If the grammar is complex (e.g., it may have many constraints/rules),


implementing this pattern becomes hard. For each rule, we may need to
implement a new class, and obviously it is a cumbersome process.
ITERATOR

DESIGN PATTERN
Definition
● GoF Definition: Provide a way to access the elements of an aggregate
object sequentially without exposing its underlying representation.
● Iterators are generally used to traverse a container to access its
elements.
Examples
1. Suppose there are two companies: Company Monitis and TV B. Company Monitis
stores its employee records(name, etc.) in a linked list and Company B stores
its employee data in a big array. One day the two companies decide to work
together. The iterator pattern is handy in such a situation. We need not write
codes from scratch. We’ll have a common interface through which we can access
data for both companies.We’ll simply call the same methods without rewriting the
codes.
2. in a college, the arts department may use array data structure and the science
department may use linked list data structure to store their students’ records.
The main administrative department will access those data through the common
methods—it doesn’t care which data structure is used by individual departments.
UML
public interface IIterator{
public interface ISubject{
void First();//Reset to first element
public IIterator CreateIterator();
String Next();//get next element
}
Boolean IsDone();//End of collection check
public class Arts implements ISubject{ String CurrentItem();//Retrieve Current Item
private String[] subjects; }
public class ArtsIterator implements IIterator{
public Arts(){
private String[] subjects;
subjects = new String[2];
private int position;
subjects[0] = "Bengali";
public ArtsIterator(String[] subjects){
subjects[1] = "English" ;
this.subjects = subjects;
}
position = 0;
public IIterator CreateIterator(){
}
return new ArtsIterator(subjects);
public void First(){
}
position = 0;
}
public String Next(){
return subjects[position++];
}
public Boolean IsDone(){
return position >= subjects.length;
}
public String CurrentItem(){
return subjects[position];
}}}
public class Science implements ISubject{
public class ScienceIterator implements IIterator{
private LinkedList<String> subjects;
private LinkedList<String> subjects;
public Science()
private int position;
{
public ScienceIterator(LinkedList<String> subjects){
subjects = new LinkedList<String>();
this.subjects = subjects;
subjects.addLast("Maths");
position = 0;
subjects.addLast("Comp. Sc.");
}
subjects.addLast("Physics");
public void First(){
}
position = 0;
@Override
}
public IIterator CreateIterator(){
public String Next(){
return new
return subjects.get(position++);
ScienceIterator(subjects);
}
}
public Boolean IsDone(){
}
return position >= subjects.size();
}
public String CurrentItem(){
return subjects.get(position);
}
}
}
class IteratorPatternEx{
public static void main(String[] args){
System.out.println("***Iterator Pattern Demo***\n");
ISubject Sc_subject = new Science();
ISubject Ar_subjects = new Arts();

IIterator Sc_iterator = Sc_subject.CreateIterator();


IIterator Ar_iterator = Ar_subjects.CreateIterator();

System.out.println("\nScience subjects :");


Print(Sc_iterator);

System.out.println("\nArts subjects :");


Print(Ar_iterator);
}

public static void Print(IIterator iterator){


while (!iterator.IsDone()){
System.out.println(iterator.Next());
}

}
}
MEDIATOR

DESIGN PATTERN
Intent
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.

Problem
Object-oriented design encourages the distribution of behavior among objects.
Such distribution can result in an object structure with many connections
between objects; in the worst case, every object ends up knowing about every
other
Real-life example: Air traffic control
● The pilots of the planes
approaching or departing the
terminal area communicate with
the tower rather than explicitly
communicating with one another.
● The constraints on who can take
off or land are enforced by the
tower.
● It is important to note that the
tower does not control the whole
flight. It exists only to
enforce constraints in the
terminal area.
Computer-world example: GUI dialog box
● A button gets disabled when a certain
entry field is empty.
● Selecting an entry in a list of choices
called a list box might change the
contents of an entry field.
● Conversely, typing text into the entry
field might automatically select one or
more corresponding entries in the list
box.
● Once text appears in the entryfield,
other buttons may become enabled that
let the user do something with the text,
such as changing or deleting the thing
to which it refers.
Class diagram
Participants
● Mediator (DialogDirector)
○ defines an interface for communicating with Colleague objects.
● ConcreteMediator (FontDialogDirector)
○ implements cooperative behavior by coordinating Colleague objects.
○ knows and maintains its colleagues.
● Colleague classes (ListBox, EntryField)
○ each Colleague class knows its Mediator object.
○ each colleague communicates with its mediator whenever it would have
otherwise communicated with another colleague.
Example #3: employee chat
Friend1 and Friend2 are
employees at Boss’s team.

● Whenever Friend1 and


Friend2 talk to each other,
Boss can see who is sending
messages
● Whenever Boss wants to send
messages, he wants his
messages to reach others
instantly
Implementation
abstract class Friend { abstract class Mediator{
protected Mediator mediator; public abstract void Send(Friend frd, String msg);
public String name; }
public Friend(Mediator mediator){
this.mediator = mediator;
}
}

class Friend1 extends Friend{ class Boss extends Friend{


public Friend1(Mediator mediator,String name){ public Boss(Mediator mediator,String name){
super(mediator); super(mediator);
this.name = name; this.name = name;
} }
public void Send(String msg){ public void Send(String msg){
mediator.Send(this,msg); mediator.Send(this, msg);
} }
public void Notify(String msg){ public void Notify(String msg){
System.out.println(name+" gets message: "+ msg); System.out.println("\nBoss sees message: " + msg);
} }
} }
class ConcreteMediator extends Mediator{ …..
private Friend1 friend1;
private Friend2 friend2; @Override
private Boss boss; public void Send(Friend frd,String msg){
//In all cases, boss is notified
//In this example, setters are sufficient. if (frd == friend1){
public void setFriend1(Friend1 friend1) { friend2.Notify(msg);
this.friend1 = friend1; boss.Notify(friend1.name + " sends message to " + friend2.name);
} }
public void setFriend2(Friend2 friend2) { If (frd == friend2){
this.friend2 = friend2; friend1.Notify(msg);
} boss.Notify(friend2.name + " sends message to " + friend1.name);
public void setBoss(Boss boss) { }
this.boss = boss; //Boss is sending message to others
} If (frd == boss){
friend1.Notify(msg);
….. friend2.Notify(msg);
}
}
}
class MediatorPatternEx{
public static void main(String[] args){
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("\n[Raghu here]:Please get back to work quickly");
}
}
Benefits and drawbacks
● Limits subclassing. A mediator localizes behavior that otherwise would be distributed
among several objects. Changing this behavior requires subclassing Mediator only;
Colleague classes can be reused as is.
● Decouples colleagues. A mediator promotes loose coupling between colleagues. You can
vary and reuse Colleague and Mediator classes independently.
● Simplifies object protocols. A mediator replaces many-to-many interactions with
one-to-many interactions between the mediator and its colleagues. One-to-many
relationships are easier to understand, maintain, and extend.
● Abstracts how objects cooperate. Making mediation an independent concept and
encapsulating it in an object lets you focus on how objects interact apart from their
individual behavior. That can help clarify how objects interact in a system.
● Centralizes control. The Mediator pattern trades complexity of interaction for
complexity in the mediator. Because a mediator encapsulates protocols, it can become
more complex than any individual colleague. This can make the mediator itself a monolith
that's hard to maintain.
MEMENTO

DESIGN PATTERN
There are 3 main participants in the memento pattern’s class
diagrams – Originator, Memento and Caretaker.

● Originator is the object of which the state is to be stored. The responsibilities of storing the
snapshot of its state and then restoring the state from Memento lie with Originator.
● Memento stores the internal state of the Originator. Only Originator is allowed storing
to/restoring from the Memento object. This allows the internal structure/state of Originator
to not be visible to other classes thus achieving the encapsulation requirement of a
Memento implementation.
● Caretaker holds the memento object and is responsible for its safekeeping. When a
snapshot of the Originator’s state is required then the Caretaker asks the Originator for the
snapshot as a memento object and stores the snapshot. When the Originator’s state is to be
restored then Caretaker passes the Memento object back to the Originator.
UML
//Originator
public class Project {

private String version;


private Date date;
public void setVersion(String version) {
this.version = version;
this.date = new Date();
}
public Save save(){
return new Save(version);
}
public void load(Save save){
this.version = save.getVersion();
this.date = save.getDate();
}
@Override
public String toString() {
return "Current project: " + "Version = " + version + ", Date=" + date ;
}
}
//Memento
public class Save {

private final String version;


private final Date date;

public Save(String version) {


this.version = version;
this.date = new Date();
}

public String getVersion() {


return version;
}

public Date getDate() {


return date;
}
}
//Caretaker
public class GitRepo {

private Map<String, Save> repo = new HashMap<String, Save>();

public void add(Save project){


repo.put(project.getVersion(), project);
}

public Save get(String version){


return repo.get(version);
}

}
public class Client {
public static void main(String[] args) throws InterruptedException {
GitRepo gitRepo = new GitRepo();
Project project = new Project();
System.out.println("---- Creating new project: Version 1.0");
project.setVersion("1.0");
System.out.println(project);
System.out.println("---- Saving current version to Git...");
gitRepo.add(project.save());
System.out.println("---- Writing poor code and Updating project to version 1.1");
Thread.sleep(5000); // optional field
project.setVersion("1.1");
System.out.println(project);
System.out.println("---- Saving current version to Git...");
gitRepo.add(project.save());
System.out.println("---- Working with current version and somethings went wrong... ");
System.out.println("---- Rolling back to version 1.0");
project.load(gitRepo.get("1.0"));
System.out.println("--------------------------------");
System.out.println(project );
}}
//Output

---- Creating new project: Version 1.0


Current project: Version = 1.0, Date=Sun Oct 29 21:08:05 AMT 2017
---- Saving current version to Git...
---- Writing poor code and Updating project to version 1.1
Current project: Version = 1.1, Date=Sun Oct 29 21:08:10 AMT 2017
---- Saving current version to Git...
Working with current version and somethings went wrong...
Rolling back to version 1.0
--------------------------------
Current project: Version = 1.0, Date=Sun Oct 29 21:08:05 AMT 2017
OBSERVER

DESIGN PATTERN
Definition
Define a one-to-many dependency between objects so that when one object changes
state, all its dependents are notified and updated automatically.

Observer - the object that watch on the state of another object

Subject - the object that is being watched


UML
Subject
Observer
Concrete Subject
Concrete Observer
STATE

DESIGN PATTERN
The State pattern is known as a behavioural pattern - it's used to manage algorithms,
relationships and responsibilities between objects.

Thedefinition of State provided in the original Gang of Four book on Design Patterns states:

Allows an object to alter its behaviour when its internal state changes. The object will appear to change its
class.

UML
The Context can have a number of internal States, whenever the request() method is called on the
Context, the message is delegated to the State to handle. The State interface defines a common
interface for all concrete states, encapsulating all behaviour associated with a particular state. The
ConcreteState implements it's own implementation for the request. When a Context changes state,
what really happens is that we have a different ConcreteState associated with it.
State saves you from lots of conditional code in your Context: by changing the ConcreteState object
used, you can change the behaviour of the context.

Would I Use This Pattern?


You should use the State pattern when the behaviour of an object should be influenced by it's state,
and when complex conditions tie object behaviour to it's state.

Watch Out for the Downsides


There are some potential bad uses of the state pattern. For example, some operations may not be
possible when the context is in certain states. This article proposes a nice solution to the problem.
//Context
private interface KidState {
public class Kid {
public void play();
private KidState kidState
public void eat();
private Kid(int age) {
}
setState(age);
}
public void play() {
kidState .play();
public class FirstKid implements KidState { public class SecondKid implements
}
public void play() { KidState {
public void eat() {
System.out.print(“Play in cradle.”); public void play() {
kidState .eat();
} System.out.print(“Play with toys.”);
}
public void eat() { }
private void setState(int age) {
System.out.print(“Drink Milk.”); public void eat() {
if(age==1){
} System.out.print(“Drink Milk and eat
kidState =new FirstKid();
} chocolate.”);
}else{
}
kidState =new SecondKid();
}
}
} public class Demo {
public static void main(String[] args) {
Kid kid = new Kid(1);
kid.play();
kid.eat();
kid = new Kid(2);
kid.play();
kid.eat();
}
}
STRATEGY

DESIGN PATTERN
Strategy design pattern
Motivation

There are common situations when classes differ only in their behavior. For
this cases is a good idea to isolate the algorithms in separate classes in
order to have the ability to select different algorithms at runtime.

Intent

Define a family of algorithms, encapsulate each one, and make them


interchangeable. Strategy lets the algorithm vary independently from clients
that use it.
Strategy pattern is also known as Policy Pattern.

One of the best example of strategy pattern is Collections.sort() method.


UML
public class CreditCard {

private String number;


private String date;
private String cvv;
private ValidationStrategy strategy;

public CreditCard(ValidationStrategy strategy) {


this.strategy = strategy;
}

public boolean isValid() {


return strategy.isValid(this);
}
getter/setter...
}
public abstract class ValidationStrategy {
public abstract boolean isValid(CreditCard creditCard);
protected boolean passesLuhn(String ccNumber) {
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--) {
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate) {
n *= 2;
if (n > 9) {n = (n % 10) + 1;}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}}
public class VisaStrategy extends ValidationStrategy {
@Override
public boolean isValid(CreditCard creditCard) {
boolean isValid = true;
isValid = creditCard.getNumber().startsWith("4");

if(isValid) {
isValid = creditCard.getNumber().length() == 16;
}
if(isValid) {
isValid = passesLuhn(creditCard.getNumber());
}

return isValid;
}
}
public class AmexStrategy extends ValidationStrategy {
@Override
public boolean isValid(CreditCard creditCard) {
boolean isValid = true;
isValid = creditCard.getNumber().startsWith("37") ||
creditCard.getNumber().startsWith("34");

if(isValid) {
isValid = creditCard.getNumber().length() == 15;
}
if(isValid) {
isValid = passesLuhn(creditCard.getNumber());
}
return isValid;
}
}
public class StrategyDemo {
public static void main(String args[]) {

CreditCard amexCard = new CreditCard(new AmexStrategy());


amexCard.setNumber("379185883464283");
amexCard.setDate("04/2020");
amexCard.setCvv("123");
System.out.println("Is Amex valid: " + amexCard.isValid());

CreditCard amexCard2 = new CreditCard(new AmexStrategy());


amexCard2.setNumber("379185883464282");
amexCard2.setDate("04/2017");
amexCard2.setCvv("234");
System.out.println("Is Amex valid: " + amexCard2.isValid());

CreditCard visaCard = new CreditCard(new VisaStrategy());


visaCard.setNumber("4539589763663402");
visaCard.setDate("05/2018");
visaCard.setCvv("324");
System.out.println("Is Visa valid: " + visaCard.isValid());
}}
OutPut
Is Amex valid: TRUE
Is Amex valid: FALSE
Is Visa valid: TRUE
TEMPLATE

DESIGN PATTERN
UML
public abstract class HouseTemplate {

public final void buildHouse(){


buildFoundation();
buildPillars();
buildWalls();
buildWindows();
System.out.println("House is built.");
}

private void buildWindows() {


System.out.println("Building Glass Windows");
}

public abstract void buildWalls();


public abstract void buildPillars();

private void buildFoundation() {


System.out.println("Building foundation with cement,iron rods and sand");
}
}
public class WoodenHouse extends HouseTemplate { public class GlassHouse extends HouseTemplate {

@Override @Override
public void buildWalls() { public void buildWalls() {
System.out.println("Building Wooden Walls"); System.out.println("Building Glass
} Walls");
}
@Override
public void buildPillars() { @Override
System.out.println("Building Pillars with public void buildPillars() {
Wood coating"); System.out.println("Building Pillars with
} glass coating");
}
}
}
public class HousingClient {
Output
public static void main(String[] args) {

HouseTemplate houseType = new Building foundation with cement,iron rods and sand
Building Pillars with Wood coating
WoodenHouse();
Building Wooden Walls
Building Glass Windows
//using template method
House is built.
houseType.buildHouse();
************
System.out.println("************");
Building foundation with cement,iron rods and sand
Building Pillars with glass coating
houseType = new GlassHouse();
Building Glass Walls
Building Glass Windows
houseType.buildHouse();
House is built.
}

}
Important points
1. Template method should consists of certain steps whose order is fixed and for some of the
methods, implementation differs from base class to subclass. Template method should be
final.
2. Most of the times, subclasses calls methods from super class but in template pattern,
superclass template method calls methods from subclasses, this is known as Hollywood
Principle – “don’t call us, we’ll call you.”.
3. Methods in base class with default implementation are referred as Hooks and they are
intended to be overridden by subclasses, if you want some of the methods to be not
overridden, you can make them final, for example in our case we can make buildFoundation()
method final because if we don’t want subclasses to override it.

Template method design pattern in JDK


● All non-abstract methods of java.io.InputStream, java.io.OutputStream, java.io.Reader and
java.io.Writer.
● All non-abstract methods of java.util.AbstractList, java.util.AbstractSet and
java.util.AbstractMap.
VISITOR

DESIGN PATTERN
The Visitor Pattern
The Visitor is known as a behavioural pattern,as it's used to manage
algorithms, relationships and responsibilities between objects. Thedefinition of
Visitor provided in the original Gang of Four book on DesignPatterns states:

Allows for one or more operation to be applied to a set of objects at runtime,


decoupling the operations from the object structure.
UML
Visitor pattern story
Suppose a first time visitor
comes to New York City. He
want to visit the city and the
city accepts his visit. Once the
visitor starts visit, it
automatically visit everything,
and he doesn't need to call a
method when he wants to go
to a museum. The travel is a
package!
interface Visitor { class FirstTimeVisitor implements Visitor {
public void visit(City city); @Override
public void visit(Museum museum); public void visit(City city) {
public void visit(Park park); System.out.println("I'm visiting the city!");
} }
@Override
public void visit(Museum museum) {
System.out.println("I'm visiting the Museum!");
}
@Override
public void visit(Park park) {
System.out.println("I'm visiting the Park!");
}
}
interface Element { class City implements Element {
public void accept(Visitor visitor); ArrayList<Element> places = new ArrayList<Element>();
} public City() {
places.add(new Museum());
places.add(new Park());
}
@Override
public void accept(Visitor visitor) {
System.out.println("City is accepting visitor.");
visitor.visit(this);

for (Element e : places) {


e.accept(visitor);
}
}
}
class Museum implements Element {
@Override
public void accept(Visitor visitor) {
System.out.println("Museum is accepting visitor.");
visitor.visit(this);
}
}
class Park implements Element {
@Override
public void accept(Visitor visitor) {
System.out.println("Park is accepting visitor.");
visitor.visit(this);
}

}
public class TestVisitor {
public static void main(String[] args) {
FirstTimeVisitor visitor = new FirstTimeVisitor();
City city = new City();
city.accept(visitor);
}
}
Output
City is accepting visitor.
I'm visiting the city!
Museum is accepting visitor.
I'm visiting the Museum!
Park is accepting visitor.
I'm visiting the Park!
public interface ProjectElement {
public void beWritten(Developer developer);
}
public class ProjectClass implements ProjectElement {
public void beWritten(Developer developer) {
developer.create(this);
}
}
public class Database implements ProjectElement{
public void beWritten(Developer developer) {
developer.create(this);
}
}
public class Test implements ProjectElement {
public void beWritten(Developer developer) {
developer.create(this);
}
}
public interface Developer { public class SeniorDeveloper implements Developer {

public void create(ProjectClass projectClass); public void create(ProjectClass projectClass) {


public void create(Database database); System.out.println("Rewriting class after junior...");
public void create(Test test);\ }

} public void create(Database database) {


System.out.println("Fixing database...");
public class JuniorDeveloper implements Developer{ }
public void create(ProjectClass projectClass) {
System.out.println("Writing poor class..."); public void create(Test test) {
} System.out.println("Creating reliable test...");
}
public void create(Database database) {
System.out.println("Drop database..."); }
}

public void create(Test test) {


System.out.println("Creating not reliable test...");
}
}
public class Project implements ProjectElement {

ProjectElement [] projectElements;

public Project() {
this.projectElements = new ProjectElement[]{
new ProjectClass(),
new Database(),
new Test()
};
}

public void beWritten(Developer developer) {


for (ProjectElement element : projectElements){
element.beWritten(developer);
}
}
}
public class ProjectRunner {
public static void main(String[] args) {
Project project = new Project();

Developer junior = new JuniorDeveloper();


Developer senior = new SeniorDeveloper();

System.out.println("Junior in action");
project.beWritten(junior);

System.out.println("\n#######################\n");

System.out.println("Junior in action");
project.beWritten(senior);
}
}
OutPut
Junior in action
Writing poor class...
Drop database...
Creating not reliable test...

#######################

Senior in action
Rewriting class after junior...
Fixing database...
Creating reliable test...
NULL OBJECT

DESIGN PATTERN
Intent

The intent of a Null Object is to encapsulate the absence of an object by providing a substitutable alternative that
offers suitable default do nothing behavior. In short, a design where "nothing will come of nothing".

Use the Null Object pattern when

● an object requires a collaborator. The Null Object pattern does not introduce this collaboration--it makes use
of a collaboration that already exists
● some collaborator instances should do nothing
● you want to abstract the handling of null away from the client

Problem

Given that an object reference may be optionally null, and that the result of a null check is to do nothing or use some
default value, how can the absence of an object — the presence of a null reference — be treated transparently?
UML
● Client -
○ requires a collaborator.
● AbstractObject -

○ declares the interface for Client's collaborator


○ implements default behavior for the interface common to all classes, as appropriate
● RealObject -

○ defines a concrete subclass of AbstractObject whose instances provide useful behavior that Client expects
● NullObject -

○ provides an interface identical to AbstractObject's so that a null object can be substituted for a real object
○ implements its interface to do nothing. What exactly it means to do nothing depends on what sort of behavior
Client is expecting
○ when there is more than one way to do nothing, more than one NullObject class may be required
public abstract class AbstractCustomer {
protected String name;
public abstract boolean isNil();
public abstract String getName();
}

public class NullCustomer extends AbstractCustomer


public class RealCustomer extends AbstractCustomer {
{
public RealCustomer(String name) {
@Override
this.name = name;
public String getName() {
}
return "Not Available in Customer Database";
}
@Override
public String getName() {
@Override
return name;
public boolean isNil() {
}
return true;
}
@Override
}
public boolean isNil() {
return false;
}
}
public class CustomerFactory {

public static final String[] names = {"Rob", "Joe", "Julie"};


public static AbstractCustomer getCustomer(String name){
for (int i = 0; i < names.length; i++) {
if (names[i].equalsIgnoreCase(name)){
return new RealCustomer(name);
}
}
return new NullCustomer();
}
}
public class NullPatternDemo {
public static void main(String[] args) {

AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");


AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");
AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");
AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");

System.out.println("Customers");
System.out.println(customer1.getName());
System.out.println(customer2.getName());
System.out.println(customer3.getName());
System.out.println(customer4.getName());
}
}
THE END

You might also like