Designpatternsinjava-171112205304.pdf

  • Uploaded by: Himanshu Srivastava
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Designpatternsinjava-171112205304.pdf as PDF for free.

More details

  • Words: 10,819
  • Pages: 208
DESIGN PATTERNS IN JAVA

Creational design patterns

FACTORY DESIGN PATTERN

Usage of Factory Design Pattern When a class doesn't know what sub-classes will be required to create

When a class wants that its sub-classes specify the objects to be created.

When the parent classes choose the creation of objects to its sub-classes.

Plan Abstract Class 1. 2. 3. 4. 5. 6. 7. 8. 9.

import java.io.*; abstract class Plan{ protected double rate; abstract void getRate(); public void calculateBill(int units){ System.out.println(units*rate); } }//end of Plan class.

Subclasses 1. 2. 3.

class DomesticPlan extends Plan{ //@override public void getRate(){

4. 5. 6.

1.

rate=3.50; } }//end of DomesticPlan class.

class

CommercialPlan

Plan{ 2. 3.

5.

public void getRate(){ rate=7.50; }

1. 2.

//@override

4.

extends

3.

class InstitutionalPlan extends Plan{ //@override public void getRate(){

4. 5. 6.

rate=5.50; } /end of InstitutionalPlan class.

1. 2.

class GetPlanFactory{ //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. 17. 18.

return null; } }//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

Window

public class MotifWidgetFactory extends WidgetFactory{

createWindow(){

public

return new PMWindow();

createWindow(){

return new MotifWindow();

};

}; public

ScrollBar return

createScrollBar(){ new

public

PMScrollBar();

ScrollBar return

} }

Window

} }

new

createScrollBar(){ MotifScrollBar();

Window with its imlpementing classes public abstract class Window{

public class MotifWindow extends Window{

public abstract void blaBlaBla();

public System.out.println(“Motif

}

void bla

blaBlaBla(){ bla

bla”)

} }

public class PMWindow extends Window{ public System.out.println(“PM } }

void bla

blaBlaBla(){ bla

bla”)

ScrollBar with its imlpementing classes public abstract class ScrollBar{

public class MotifScrollBar extends ScrollBar{

public abstract void blaBlaBla();

public System.out.println(“Motif

}

void bla

blaBlaBla(){ bla

bla”)

} }

public class PMScrollBar extends ScrollBar{ public System.out.println(“PM } }

void bla

blaBlaBla(){ 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 In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a singleton class but it has a drawback that instance is created even though client application might not be using it.

public class EagerInitializedSingleton { private static final EagerInitializedSingleton instance = new EagerInitializedSingleton(); //private constructor to avoid client applications to use constructor private EagerInitializedSingleton(){} public static EagerInitializedSingleton getInstance(){ return instance; } }

public class LazyInitializedSingleton {

Lazy Initialization

private static LazyInitializedSingleton instance; private LazyInitializedSingleton(){} public static LazyInitializedSingleton getInstance(){ if(instance == null){ instance = new LazyInitializedSingleton(); } return instance; } }

Lazy initialization method to implement Singleton pattern creates the instance in the global access method. Here is the sample code for creating Singleton class with this approach.

Static block initialization Static block initialization implementation is similar to eager initialization, except that instance of class is created in the static block that provides option for exception handling.

public class StaticBlockSingleton { private static StaticBlockSingleton instance; private StaticBlockSingleton(){} //static block initialization for exception handling static{ try{ instance = new StaticBlockSingleton(); }catch(Exception e){ throw new RuntimeException("Exception occured in creating singleton instance"); } } public static StaticBlockSingleton getInstance(){ return instance; } }

Thread Safe Singleton public class ThreadSafeSingleton { private static ThreadSafeSingleton instance; private ThreadSafeSingleton(){} public static synchronized ThreadSafeSingleton getInstance(){ if(instance == null){ instance = new ThreadSafeSingleton(); } return instance; } }

The easier way to create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time. public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){ if(instance == null){ synchronized (ThreadSafeSingleton.class) { if(instance == null){ instance = new ThreadSafeSingleton(); } } } return instance; }

Bill Pugh Singleton Implementation public class BillPughSingleton {

Bill Pugh came up with a different approach to create the Singleton class using a inner static helper class. The Bill Pugh Singleton implementation goes like this

private BillPughSingleton(){} private static class SingletonHelper{ private static final BillPughSingleton INSTANCE = new BillPughSingleton(); } 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 public public public

abstract class BasicCar implements Cloneable{ String modelname; int price; 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 Ford(String m){

public Nano(String m){ modelname = m;

modelname = m;

}

}

@Override

@Override

public BasicCar clone() throws CloneNotSupportedException{

public BasicCar clone() throws CloneNotSupportedException{ return (Ford)super.clone(); } }

return (Nano)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 Implementing the cloning mechanism if the objects under consideration copying or if there is any kind of

cloning mechanism. can be challenging do not support 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 1.

public interface Packing {

2.

public String pack();

3.

public int price();

4.

Create 2 abstract classes CD and Company 1.

public abstract class CD implements Packing{

2.

public abstract String pack();

3.

}

1.

public abstract class Company extends CD{

}

2. 3.

public abstract int price(); }

Create 2 implementation classes of Company: Sony and Samsung 1.

public class Sony extends Company{

2.

@Override

3.

return 20;

5.

}

6.

@Override

7.

public String pack(){

8.

return "Sony CD";

9. 10.

} }

public class Samsung extends Company {

2.

public int price(){

4.

1.

@Override

3.

public int price(){

4.

return 15;

5.

}

6.

@Override

7.

public String pack(){

8.

return "Samsung CD";

9. 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 ArrayList<Packing>(); public void addItem(Packing packs) { items.add(packs); } public void getCost(){ for (Packing packs : items) { packs.price(); } }

System.out.println(", Price : "+packing.price()); } } }//End of the CDType class.

Create the BuilderDemo class

Create the CDBuilder class

1.

public class CDBuilder {

1.

public class BuilderDemo{

2.

public CDType buildSonyCD(){

2.

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();

public static void main(String args[]){

6.

}

6.

7.

public CDType buildSamsungCD(){

7.

CDType cdType2=cdBuilder.buildSamsungCD(); cdType2.showItems();

8.

CDType cds=new CDType();

8.

9.

cds.addItem(new Samsung());

9.

10.

return cds;

11. 12.

} }

10.

} }

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.

public class User { //All final attributes private final String firstName; // required private final String lastName; // required private final int age; // optional private final String phone; // optional private final String address; // optional private User(UserBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.age = builder.age; this.phone = builder.phone; this.address = builder.address; }

//All getter, and NO setter to provde immutability public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } public String getPhone() { return phone; } public String getAddress() { return address; } @Override public String toString() { return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address; }

public static class UserBuilder { private final String firstName; private final String lastName; private int age; private String phone; private String address; public UserBuilder(String firstName, String lastName) {

//Return the finally consrcuted User object public User build() { User user = new User(this); validateUserObject(user); return user; } private void validateUserObject(User user) { //Do some basic validations to check //if user object does not break any assumption of system } } }

this.firstName = firstName; this.lastName = lastName; } public UserBuilder address(String address) { this.address = address; return this;

public static void main(String[] args) { User user1 = new User.UserBuilder("Name", "LastName") .age(30) .phone("1234567") .address(" address 1234") .build();

}

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 { private Set available = new HashSet<>(); private Set 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) { inUse.remove(instance);

private static int counter = 1; 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 {

public static void main(String[] args) { OliphauntPool pool = new OliphauntPool(); LOGGER.info(pool.toString());

@Override

Oliphaunt oliphaunt1 = pool.checkOut();

protected Oliphaunt create() {

LOGGER.info("Checked out {}", oliphaunt1); 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 interface:

//Concrete Implementor public class Sony implements TV {

//Implementor

void on() { // Sony specific on }

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

And then we create two specific implementations - one for Sony and one for Philips:

public void off() { // Sony specific off } public void tuneChannel(int channel) { // Sony specific tuneChannel } }

//Concrete Implementor public class Philips implements TV { public void on() { // Philips specific on } public void off() { // Philips specific off } public void tuneChannel(int channel) { // Philips specific tuneChannel }

Now, we create a remote control abstraction to control the TV: //Abstraction public abstract class RemoteControl { private TV implementor; public void on() { implementor.on(); } 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 void applyColor(); }

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

public abstract class Shape { //Composition - implementor protected Color color; //constructor with implementor as input argument public Shape(Color c){ this.color=c; } abstract public void applyColor(); }

public class Pentagon extends Shape{

public class RedColor implements Color{

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

public void applyColor(){ System.out.println("red."); } }

public class GreenColor implements 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 public class Drawing implements Shape{ //collection of Shapes private List<Shape> shapes = new ArrayList<Shape>(); @Override public void draw(String fillColor) { for(Shape sh : shapes) { sh.draw(fillColor); } }

//adding shape to drawing public void add(Shape s){ this.shapes.add(s); } //removing shape from drawing public void remove(Shape s){ shapes.remove(s); } //removing all the shapes public void clear(){ System.out.println("Clearing all the shapes from drawing"); this.shapes.clear(); } }

Example public class TestCompositePattern {

drawing.draw("Red");

public static void main(String[] args) { Shape tri = new Triangle(); Shape tri1 = new Triangle(); Shape cir = new Circle(); Drawing drawing = new Drawing(); drawing.add(tri1); drawing.add(tri1); drawing.add(cir);

drawing.clear(); drawing.add(tri); drawing.add(cir); drawing.draw("Green"); } }

Output Drawing Drawing Drawing Clearing Drawing Drawing

Triangle with color Red Triangle with color Red Circle with color Red all the shapes from drawing Triangle with color Green 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).

abstract class Component{ public abstract void doJob(); }

class ConcreteComponent extends Component { @Override public void doJob(){ System.out.println(" I am from Concrete Component-I am closed for modification."); } }

abstract class AbstractDecorator extends Component{ protected Component com ; public void SetTheComponent(Component c){ com = c; } public void doJob(){ if (com != null){ com.doJob(); } } }

class ConcreteDecoratorEx_1 extends AbstractDecorator{ public void doJob(){ super.doJob(); //Add additional thing if necessary System.out.println("I am explicitly from Ex_1"); }} class ConcreteDecoratorEx_2 extends AbstractDecorator{ public void doJob(){ System.out.println(""); System.out.println("***START Ex-2***"); super.doJob(); //Add additional thing if necessary System.out.println("Explicitly From DecoratorEx_2"); System.out.println("***END. EX-2***"); }} public static void main(String[] args){ System.out.println("***Decorator pattern Demo***"); ConcreteComponent cc = new ConcreteComponent(); ConcreteDecoratorEx_1 cd_1 = new ConcreteDecoratorEx_1(); // Decorating ConcreteComponent Object //cc with ConcreteDecoratorEx_1 cd_1.SetTheComponent(cc); 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 void CreateBody(){ System.out.println("Body Creation done"); }} public class RobotColor{ private String color; public void SetColor(String color){ this.color = color; System.out.println("Color is set to : "+ this.color); } }

public class RobotMetal{ private String metal; public void SetMetal(String metal){ this.metal=metal; System.out.println("Metal is set to : "+this.metal); } }

public class RobotFacade{ RobotColor rc; RobotMetal rm ; RobotBody rb; public RobotFacade(){ rc = new RobotColor(); rm = new RobotMetal(); rb = new RobotBody(); } public void ConstructRobot(String color,String metal){ System.out.println("\nCreation of the Robot Start"); rc.SetColor(color); rm.SetMetal(metal); rb.CreateBody(); System.out.println(" \nRobot Creation End"); System.out.println(); }} class FacadePatternEx{ public static void main(String[] args){ System.out.println("***Facade Pattern Demo***"); 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 { void draw(); } public class Circle implements Shape { private String color; private int x; private int y; private int radius; public Circle(String color){ this.color = color; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setRadius(int radius) { this.radius = radius; } @Override public void draw() { System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius); } }

public class ShapeFactory { private static final HashMap<String, Shape> circleMap = new HashMap(); public static Shape getCircle(String color) { Circle circle = (Circle)circleMap.get(color); if(circle == null) { circle = new Circle(color); circleMap.put(color, circle); System.out.println("Creating circle of color : " + color); } return circle; } } public class FlyweightPatternDemo { private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" }; public static void main(String[] args) { for(int i=0; i < 20; ++i) { Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); 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 It It be

reduces the coupling. adds flexibility while assigning the responsibilities to objects. allows a set of classes to act as one; events produced in one class can 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 { private int amt;

abstract class NoteModule{ protected NoteModule next; abstract void takeMoney(Money money); public void setNextMoneyModule(NoteModule next) { this.next = next; }

public Money(int amt) { setAmt(amt) } public int getAmt() { return amt; } public void setAmt(int amt) { if(amt> 0 && amt<=200_000 && amt%Note.AMD1000==0){ this.amt = amt; }else{ throw new RuntimeException("Error"); }} }

}

class Note{ public static final int AMD1000 = 1000; public static final int AMD5000 = 5000; public static final int AMD10000 = 10000; public static final int AMD20000 = 20000; }

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 + " - " + Note.AMD1000);

System.out.println(countNote + " - " + 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 + " - " + Note.AMD10000);

System.out.println(countNote + " - " + 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 public class LightOnCommand implements Command{

//Concrete Command public class LightOffCommand implements 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{ private boolean on; public void switchOn(){

//Client public class Client{ public static void main(String[] args)

{

RemoteControl control = new RemoteControl();

on = true; }

Light light = new Light();

public void switchOff(){

Command lightsOn = new LightsOnCommand(light); Command lightsOff = new LightsOffCommand(light);

on = false;

//switch on

}

control.setCommand(lightsOn);

}

control.pressButton(); //Invoker

//switch off

public class RemoteControl{

control.setCommand(lightsOff);

private Command command; public void setCommand(Command command){ this.command = command; } public void pressButton(){ command.execute(); } }

control.pressButton(); } }

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; import java.util.Scanner; /*Context class: interpretation is carried out based on our implementation.*/

class Context{ public String input; public Context(String input){ this.input=input; } public void getBinaryForm(String input){ int i = Integer.parseInt(input); //integer to its equivalent binary string representation String binaryString = Integer.toBinaryString(i); System.out.println("Binary equivalent of "+input+ " is "+ binaryString); }

interface IExpression { void interpret(Context ic); }

class StringToBinayExp implements IExpression { private String str; public StringToBinaryExp(String s) { str = s; } @Override public void interpret(Context ic) { ic.getBinaryForm(str); } }

public void printInWords(String input) { this.input = input; System.out.println("Printing the input in words:"); char c[]=input.toCharArray(); for(int i=0;i
class IntToWords implements IExpression {

private String str; public IntToWords(String str) { this.str = str; } @Override public void interpret(Context ic) { ic.printInWords(str); }

}

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.

2.

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. 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 ISubject{ public IIterator CreateIterator(); }

public interface IIterator{ void First();//Reset to first element String Next();//get next element Boolean IsDone();//End of collection check

public class Arts implements ISubject{ private String[] subjects; public Arts(){ subjects = new String[2]; subjects[0] = "Bengali"; subjects[1] = "English" ;

String CurrentItem();//Retrieve Current Item } public class ArtsIterator implements IIterator{ private String[] subjects; private int position; public ArtsIterator(String[] subjects){ this.subjects = subjects;

} public IIterator CreateIterator(){ return new ArtsIterator(subjects); }

position = 0; } 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{ private LinkedList<String> subjects; public Science()

public class ScienceIterator implements IIterator{ private LinkedList<String> subjects; 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 ScienceIterator(subjects);

return subjects.get(position++); }

}

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 { protected Mediator mediator; public String name; public Friend(Mediator mediator){ this.mediator = mediator; } }

abstract class Mediator{ public abstract void Send(Friend frd, String msg); }

class Friend1 extends Friend{ public Friend1(Mediator mediator,String name){ super(mediator); this.name = name; } public void Send(String msg){ mediator.Send(this,msg); } public void Notify(String msg){ System.out.println(name+" gets message: "+ msg); } }

class Boss extends Friend{ public Boss(Mediator mediator,String name){ super(mediator); this.name = name; } public void Send(String msg){ mediator.Send(this, msg); } public void Notify(String msg){ System.out.println("\nBoss sees message: " + msg); } }

class ConcreteMediator extends Mediator{ private Friend1 friend1; private Friend2 friend2; private Boss boss;

….. @Override public void Send(Friend frd,String msg){ //In all cases, boss is notified if (frd == friend1){ friend2.Notify(msg); boss.Notify(friend1.name + " sends message to " + friend2.name); } If (frd == friend2){ friend1.Notify(msg); boss.Notify(friend2.name + " sends message to " + friend1.name); } //Boss is sending message to others If (frd == boss){ friend1.Notify(msg); friend2.Notify(msg); } }

//In this example, setters are sufficient. public void setFriend1(Friend1 friend1) { this.friend1 = friend1; } public void setFriend2(Friend2 friend2) { this.friend2 = friend2; } public void setBoss(Boss boss) { this.boss = boss; } …..

}

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 public class Kid { private KidState kidState private Kid(int age) { setState(age); } public void play() { kidState .play(); } public void eat() { kidState .eat(); } private void setState(int age) { if(age==1){ kidState =new FirstKid(); }else{ kidState =new SecondKid(); } }

private interface KidState { public void play(); public void eat(); }

public class FirstKid implements KidState { public void play() { System.out.print(“Play in cradle.”); } public void eat() { System.out.print(“Drink Milk.”); } }

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(); } }

public class SecondKid implements KidState { public void play() { System.out.print(“Play with toys.”); } public void eat() { System.out.print(“Drink Milk and eat chocolate.”); } }

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 private private private

String number; String date; String cvv; 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 } if(isValid) isValid }

{ = creditCard.getNumber().length() == 16; { = 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 { @Override public void buildWalls() { System.out.println("Building Wooden Walls"); } @Override public void buildPillars() { System.out.println("Building Pillars with Wood coating"); }

public class GlassHouse extends HouseTemplate { @Override public void buildWalls() { System.out.println("Building Glass Walls"); } @Override public void buildPillars() { System.out.println("Building Pillars with glass coating"); }

} }

public class HousingClient { public static void main(String[] args) { HouseTemplate houseType = new WoodenHouse(); //using template method houseType.buildHouse(); System.out.println("************"); houseType = new GlassHouse(); houseType.buildHouse(); } }

Output Building foundation with cement,iron rods and sand Building Pillars with Wood coating Building Wooden Walls Building Glass Windows House is built. ************ Building foundation with cement,iron rods and sand Building Pillars with glass coating Building Glass Walls Building Glass Windows House is built.

Important points 1.

2.

3.

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. 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.”. 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 { public void visit(City city); public void visit(Museum museum); public void visit(Park park); }

class FirstTimeVisitor implements Visitor { @Override public void visit(City city) { 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 { public void accept(Visitor visitor); }

class City implements Element { 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(Database database); public void create(Test test);\

public void create(ProjectClass projectClass) { System.out.println("Rewriting class after junior..."); }

}

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(Database database) { System.out.println("Drop database..."); } public void create(Test test) { System.out.println("Creating not reliable test..."); } }

public void create(Test test) { System.out.println("Creating 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 RealCustomer extends AbstractCustomer {

public class NullCustomer extends AbstractCustomer {

public RealCustomer(String name) { this.name = name; }

@Override public String getName() { return "Not Available in Customer Database"; }

@Override public String getName() { return name; } @Override public boolean isNil() { return false; } }

@Override public boolean isNil() { return true; } }

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

More Documents from "Himanshu Srivastava"