0% found this document useful (0 votes)
5 views

Module 10 DesginPattersIntro L1 L4

The document discusses design patterns in Java, particularly focusing on the Gang of Four (GoF) patterns, which provide reusable solutions to common software design problems. It categorizes these patterns into Creational, Structural, and Behavioral patterns, detailing specific examples such as Singleton, Factory, and Builder patterns. The document emphasizes the importance of these patterns in creating flexible, maintainable, and efficient object-oriented software.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

Module 10 DesginPattersIntro L1 L4

The document discusses design patterns in Java, particularly focusing on the Gang of Four (GoF) patterns, which provide reusable solutions to common software design problems. It categorizes these patterns into Creational, Structural, and Behavioral patterns, detailing specific examples such as Singleton, Factory, and Builder patterns. The document emphasizes the importance of these patterns in creating flexible, maintainable, and efficient object-oriented software.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 77

Object Oriented Programming

BITS Pilani Dr. Tanmaya Mahapatra and Asish Bera


Computer Science & Information Systems
Pilani Campus
BITS Pilani
Pilani Campus

Design Patterns in Java


(Module- 10a)
Introduction
In the late 70’s (1977), an architect named Christopher Alexander started the concept of patterns.
Christopher had said that “Each pattern describes a problem that occurs over and over again in
our environment, and then describes the core of the solution to that problem, in such a way
that you can use this solution a million times over, without ever doing it the same way twice”.

Later, the Gang of Four - Design patterns, elements of reusable object-oriented software book
was written by a group of four persons named as Erich Gamma, Richard Helm, Ralph Johnson
and John Vlissides in 1995.
That's why all the above 23 Design Patterns are known as Gang of Four (GoF) Design Patterns.

As an Object Oriented developer, we may think that our code contains all the benefits provided by
the Object Oriented language.
The code we have written is flexible enough that we can make any changes to it easily.
Our code is re-usable so that we can re-use it anywhere without any trouble.
We can maintain our code easily and any changes to a part of the code will not affect any other
part of the code.

BITS Pilani, Pilani Campus


Contd…

 reusable in multiple projects.

 capture the software engineering experiences.

 provide transparency to the design of an application.

 well-proved and testified solutions since they have been built upon the knowledge and
experience of expert software developers.

 don’t guarantee an absolute solution to a problem.

 provide the solutions that help to define the system architecture.

 provide clarity to the system architecture and the possibility of building a better system.

BITS Pilani, Pilani Campus


Categories

1.Creational Design Pattern (object creation)


3. Behavioural Design Pattern
(class/object interaction)
a. Factory Pattern
b. Abstract Factory Pattern a. Chain Of Responsibility Pattern
b. Command Pattern
c. Singleton Pattern c. Interpreter Pattern
d. Prototype Pattern 2. Structural Design Pattern d. Iterator Pattern
(composition of class and object) e. Mediator Pattern
e. Builder Pattern f. Memento Pattern
a. Adapter Pattern g. Observer Pattern
b. Bridge Pattern h. State Pattern
c. Composite Pattern i. Strategy Pattern
d. Decorator Pattern j. Template Pattern
e. Facade Pattern k. Visitor Pattern
f. Flyweight Pattern
g. Proxy Pattern
BITS Pilani, Pilani Campus
BITS Pilani
Pilani Campus

Creational Design Patterns in Java


(Module- 10a)
Creational Design Pattern

Creational design patterns are concerned with the way of creating objects.
These design patterns are used when a decision must be made at the time of
instantiation of a class (i.e. creating an object of a class).
1. Singleton Pattern
The singleton pattern restricts the instantiation of a Class and ensures that
only one instance of the class exists in the JVM.
2. Factory Pattern
• The factory design pattern is used when, we have a superclass with multiple
subclasses and based on input, we need to return one of the subclasses.
• This pattern takes out the responsibility of the instantiation of a Class from the
client program to the factory class. We can apply a singleton pattern on the
factory class or make the factory method static.
BITS Pilani, Pilani Campus
Factory Pattern

• A Factory Pattern says that just define an interface or abstract class for
creating an object, but let the subclasses decide which class to
instantiate. In other words, subclasses are responsible to create the instance
of the class.
• Factory Pattern allows the sub-classes to choose the type of objects to create.
• It promotes the loose-coupling by eliminating the need to bind application-
specific classes into the code.
• The code interacts solely with the resultant interface or abstract class, so that
it will work with any classes that implement that interface or extends the
abstract class.

BITS Pilani, Pilani Campus


Abstract Factory and Builder Patterns
3. Abstract Factory Pattern
It solves the problem of creating entire product families without specifying their
concrete classes.
It is similar to the factory pattern and is a factory of factories. If you are
familiar with the factory design pattern in Java, you will notice that we have a
single factory class. In the abstract factory pattern, we have a factory class for
each subclass, and then an abstract factory class that will return the subclass
based on input factory class.
4. Builder Pattern
It was introduced to solve some of problems with Factory and Abstract Factory
patterns, when the object contains a lot of attributes.
It solves the issue with a large number of optional parameters and inconsistent
state by providing a way to build the object step-by-step and provide a method
that will actually return the final Object.
BITS Pilani, Pilani Campus
Singleton Pattern

Singleton pattern is one of the simplest design


patterns.
It provides one of the best ways to create an object.
This pattern involves a single class which is responsible
to create an object while making sure that only single
object gets created.
This class provides a way to access its only object
which can be accessed directly without need to
instantiate the object of the class.

BITS Pilani, Pilani Campus


Contd…
public class SingleObject {
//create an object of SingleObject
private static SingleObject instance = new SingleObject();

// private constructor so that the class cannot be instantiated


private SingleObject(){ }

//Get the only object available public class SingletonPatternDemo {


public static SingleObject getInstance(){ public static void main(String[ ] args) {
return instance; SingleObject object = SingleObject.getInstance();
} object.showMessage();
public void showMessage(){ }
System.out.println("Hello World!"); }
Hello World!
}
}
BITS Pilani, Pilani Campus
Factory Pattern

Creates object without exposing the creation


logic to the client, and refer to newly created
object using a common interface.

public interface Shape { void draw(); }

public class Rectangle implements Shape {


public void draw() {
System.out.println("Inside Rectangle:draw() method");
}}
public class Square implements Shape {public void draw() {
System.out.println("Inside Square::draw() method."); } }

public class Circle implements Shape {


public void draw() { System.out.println("Inside Circle::draw() method."); }
}

BITS Pilani, Pilani Campus


Contd …
public class ShapeFactory {
//use getShape method to get object of type shape public class FactoryPatternDemo {
public Shape getShape(String shapeType){ public static void main(String[ ] args) {
if(shapeType == null){ ShapeFactory shapeFactory = new ShapeFactory();
//get an object of Circle and call its draw method.
return null; }
Shape shape1 = shapeFactory.getShape("CIRCLE");
if(shapeType.equalsIgnoreCase("CIRCLE")){ shape1.draw(); //call draw method of Circle
return new Circle(); //get an object of Rectangle and call its draw method.
} else if(shapeType.equalsIgnoreCase("RECTANGLE")) Shape shape2 = shapeFactory.getShape("RECTANGLE");
{ return new Rectangle(); shape2.draw(); //call draw method of Rectangle
//get an object of Square and call its draw method.
} else if(shapeType.equalsIgnoreCase("SQUARE")){
Shape shape3 = shapeFactory.getShape("SQUARE");
return new Square(); //call draw method of square
} shape3.draw();
return null; }
} }
}

BITS Pilani, Pilani Campus


Abstract Factory Pattern
//3 Create an Abstract
class to get // Step 6 Use FactoryProducer to
factories get AbstractFactory to get factories
for both of concrete classes
Shape Objects.

// Step 5 Create a Factory producer


// 4 Create Factory class to get factories
classes extending
AbstractFactory to
generate object of
concrete class //1 Create an interface for Shapes
https://www.tutorialspoint.com/design_pattern/abstract_factory_pattern.htm

//2 Create concrete class implementing Shape interface.

BITS Pilani, Pilani Campus


Implementation
//1 Create an interface for Shapes.
public interface Shape {
void draw();
}

//2 Create concrete class implementing Shape interface.


public class RoundedRectangle implements Shape {
public void draw() {
System.out.println("Inside RoundedRectangle::draw() method.");
}
}

//3 Create an Abstract class to get factories for both Shape Objects.
public abstract class AbstractFactory {
abstract Shape getShape(String shapeType) ;
}
BITS Pilani, Pilani Campus
Contd …
// 4 Create Factory classes extending AbstractFactory to generate object of concrete class
based on given information.

public class ShapeFactory extends AbstractFactory {


public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")) public class RoundedShapeFactory extends AbstractFactory {
{ return new Rectangle(); } public Shape getShape(String shapeType){
else if(shapeType.equalsIgnoreCase("SQUARE")) if(shapeType.equalsIgnoreCase("RECTANGLE")){
{ return new Square(); } return new RoundedRectangle();
return null; }else if(shapeType.equalsIgnoreCase("SQUARE")){
} return new RoundedSquare();
} }
return null;
}
}

BITS Pilani, Pilani Campus


Contd …

// Step 5 Create a Factory generator/producer class to get factories by passing


an information such as Shape

public class FactoryProducer {


public static AbstractFactory getFactory(boolean rounded){
if(rounded){
return new RoundedShapeFactory();
}else{
return new ShapeFactory();
}
}

BITS Pilani, Pilani Campus


Contd …
// Step 6 Use FactoryProducer to get AbstractFactory to get factories of concrete classes by passing type information
public class AbstractFactoryPatternDemo {
public static void main(String[ ] args) {
AbstractFactory shapeFactory = FactoryProducer.getFactory(false); //get shape factory
Shape shape1 = shapeFactory.getShape("RECTANGLE"); //get an object of Shape Rectangle
//call draw method of Shape Rectangle
shape1.draw(); //get an object of Shape Square
Shape shape2 = shapeFactory.getShape("SQUARE");
shape2.draw(); //call draw method of Shape Square
//get shape factory
AbstractFactory shapeFactory1 = FactoryProducer.getFactory(true); //get an object of Shape Rectangle
Shape shape3 = shapeFactory1.getShape("RECTANGLE"); //call draw method of Shape Rectangle
shape3.draw(); //get an object of Shape Square
Shape shape4 = shapeFactory1.getShape("SQUARE");
shape4.draw(); //call draw method of Shape Square
}
}

BITS Pilani, Pilani Campus


Prototype Design Pattern

It is a creational design pattern. Cloning of an existing object instead of


creating new one and can also be customized as per the requirement.
Prototype patterns are required, when object creation is time consuming, and
costly operation, so we create objects with the existing object itself.
One of the best available ways to create an object from existing objects is
the clone() method.
Deep Copy vs. Shallow Copy: The Prototype pattern raises the issue of
whether to perform a deep copy or a shallow copy when cloning objects.
A shallow copy may result in objects sharing references to the same underlying
data, leading to unintended side effects.
A deep copy can be resource-intensive and may require implementing custom
cloning logic for all associated objects.
BITS Pilani, Pilani Campus
Example

BITS Pilani, Pilani Campus


BasicCar
import java.util.Random;
public abstract class BasicCar implements Cloneable{
public String modelName;
public int basePrice,onRoadPrice;
public String getModelname() {
return modelName; }
public void setModelname(String modelname) {
this.modelName = modelname; }
public static int setAdditionalPrice()
{
int price = 0;
Random r = new Random();
//We will get an integer value in the range 0 to 100000
int p = r.nextInt(100000);
price = p;
return price;
}
public BasicCar clone() throws CloneNotSupportedException
{return (BasicCar)super.clone(); }
}

BITS Pilani, Pilani Campus


class Nano extends BasicCar
{
//A base price for Nano
public int basePrice=100000;
public Nano(String m)
{
modelName = m;
}
public BasicCar clone() throws CloneNotSupportedException
{
return (Nano)super.clone();
}
}

BITS Pilani, Pilani Campus


class Ford extends BasicCar
{
public int basePrice=100000;
public Ford(String m)
{
modelName = m;}
public BasicCar clone() throws CloneNotSupportedException
{
return (Ford)super.clone();
}
}

BITS Pilani, Pilani Campus


public class PrototypePatternExample {
public static void main(String[ ] args) throws
CloneNotSupportedException { Car is: Green Nano and it's price is
System.out.println("***Prototype Pattern Demo***\n"); Rs.123806
BasicCar nano = new Nano("Green Nano") ; Car is: Ford Yellow and it's price is
nano.basePrice=100000; Rs.595460
BasicCar ford = new Ford("Ford Yellow");
ford.basePrice=500000;
BasicCar bc1;
bc1 =nano.clone(); //Nano
bc1.onRoadPrice = nano.basePrice+BasicCar.setAdditionalPrice();
System.out.println("Car is: "+ bc1.modelName+" and it's price is
Rs."+bc1.onRoadPrice);
bc1 =ford.clone(); //Ford
bc1.onRoadPrice = ford.basePrice+BasicCar.setAdditionalPrice();
System.out.println("Car is: "+ bc1.modelName+" and it's price is
Rs."+bc1.onRoadPrice); }
}
BITS Pilani, Pilani Campus
Builder design pattern
Builder — A creational design pattern that lets you construct
complex objects step by step. The pattern allows you to produce
different types and representations of an object using the same
construction code.
Builder design pattern consists of components such as builder
interface, concrete builders, product, and client.
Product is the complex object that you want to create.
ConcreteBuilder constructs and assembles the parts of a product
by implementing an abstract interface Builder.
ConcreteBuilder objects build the product’s internal representation
and define the creational process/assembling mechanisms.
Builders can also provide methods to get an object that is created and
available for use.
Director is responsible for creating final object using Builder interface.
Director uses Builder and controls the steps/sequence to build the
final Product. Builders can also keep reference of the products that
they built, so that they can be used again.

BITS Pilani, Pilani Campus


Example

BITS Pilani, Pilani Campus


interface Builder
{
void startUpOperations();
void buildBody();
void insertWheels();
void addHeadlights();
void endOperations();
/*The following method is used to retrieve the object that is constructed.*/
Product getVehicle();
}

BITS Pilani, Pilani Campus


public void buildBody()
{product.add("This is a body of a Car");}
class Car implements Builder
{ public void insertWheels()
private String brandName; {product.add("4 wheels are added");}
private Product product; public void addHeadlights()
public Car(String brand) {product.add("2 Headlights are added");}
{
product = new Product();
public void endOperations()
this.brandName = brand; { //Nothing in this case}
} public Product getVehicle()
public void startUpOperations() {return product;}
{ }
//Starting with brand name
product.add(String.format("Car model is :%s",this.brandName));
}
BITS Pilani, Pilani Campus
Product class
class Product
{ /* You can use any data structure that you prefer. */
private LinkedList<String> parts;
public Product()
{parts = new LinkedList<String>();
}
public void add(String part)
{ //Adding parts
parts.addLast(part);
}
public void showProduct()
{ System.out.println("\nProduct completed as below :");
for (String part: parts)
System.out.println(part);
}
}

BITS Pilani, Pilani Campus


Director class

class Director
{Builder builder;
// Director knows how to use the builder and the sequence of steps.
public void construct(Builder builder)
{
this.builder = builder;
builder.startUpOperations();
builder.buildBody();
builder.insertWheels();
builder.addHeadlights();
builder.endOperations();
}
}
BITS Pilani, Pilani Campus
public class BuilderPatternExample {
public static void main(String[ ] args) {
System.out.println("***Builder Pattern Demo***");
Director director = new Director();
Builder fordCar = new Car("Ford");
Builder hondaMotorycle = new MotorCycle("Honda");
director.construct(fordCar);
Product p1 = fordCar.getVehicle();
p1.showProduct();
director.construct(hondaMotorycle ); //Making MotorCycle
Product p2 = hondaMotorycle.getVehicle();
p2.showProduct();
}}
BITS Pilani, Pilani Campus
Example

BITS Pilani, Pilani Campus


Builder Example
public class Employee { public static class EmployeeBuilder {
private String name; private String name;
private String company; private String company;
private boolean hasCar;//optional
private boolean hasCar;//optional private boolean hasBike;//optional
private boolean hasBike;//optional //constructor for required fields
private Employee(EmployeeBuilder employeeBuilder) { public EmployeeBuilder(String name, String company) {
name = employeeBuilder.name; this.name = name;
company = employeeBuilder.company; this.company = company; }
hasCar = employeeBuilder.hasCar; //setter methods for optional fields
hasBike = employeeBuilder.hasBike; public EmployeeBuilder setHasCar(boolean hasCar) {
this.hasCar = hasCar;
} return this; }
public String getName() { public EmployeeBuilder setHasBike(boolean hasBike) {
return name; } this.hasBike = hasBike;
public String getCompany() { return this; }
return company; //Build the Employee object
} public Employee build() { return new Employee(this); } }}
public boolean isHasCar() { class TestBuilder {
public static void main(String[] args) {
return hasCar; } //Building the object of Employee thru build() method in EmployeeBuilder class.
public boolean isHasBike() { Employee employee = new Employee.EmployeeBuilder("Vikram",
return hasBike; } "ABC").setHasBike(false).setHasBike(true).build();
}
}
BITS Pilani, Pilani Campus
BITS Pilani
Pilani Campus

Structural Design Patterns in Java


(Module- 10b)
Adapter Pattern
Converts the interface of a class into another interface that a client wants.
• Provides an interface according to client requirement while using the services
of a class with a different interface.
• Allows two or more incompatible objects to interact.
• Allows reusability of existing functionality.

• The adapter translates that request on the adaptee using the adaptee interface.
• Client receive the results of the call and is unaware of adapter’s presence.
• Client requests to the adapter by calling a method on it using target interface.

BITS Pilani, Pilani Campus


Specifications of 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 class 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.

BITS Pilani, Pilani Campus


Example
interface Bird
{ // birds implement Bird interface that allows them to fly and make sounds adaptee interface
public void fly();
public void makeSound(); Problem: Suppose you have a Bird class with fly() ,
} and makeSound()methods. And also a ToyDuck class
class Sparrow implements Bird with squeak() method. Let’s assume that you are
{ // a concrete implementation of bird short on ToyDuck objects and you would like to use
public void fly() Bird objects in their place.
{ System.out.println("Flying"); } Birds have some similar functionality but implement
public void makeSound() a different interface, so we can’t use them directly. So
{ System.out.println("Chirp Chirp"); } we will use adapter pattern. Here our client would be
} ToyDuck and adaptee would be Bird.
interface ToyDuck
{ // target interface toyducks dont fly they just make squeaking sound
public void squeak();
}
BITS Pilani, Pilani Campus
Code
class Main{
class PlasticToyDuck implements ToyDuck{ public static void main(String args[]) {
public void squeak()
Sparrow sparrow = new Sparrow();
{ System.out.println("Squeak");}
ToyDuck toyDuck = new PlasticToyDuck();
}
class BirdAdapter implements ToyDuck
// Wrap a bird in a birdAdapter so that it
{ // You need to implement the interface your // behaves like toy duck
// client expects to use. ToyDuck birdAdapter = new BirdAdapter(sparrow);
Bird bird; System.out.println("Sparrow...");
public BirdAdapter(Bird bird) { sparrow.fly();
// we need reference to the object we sparrow.makeSound();
// are adapting System.out.println("ToyDuck...");
this.bird = bird; } toyDuck.squeak();
public void squeak() // toy duck behaving like a bird
{ System.out.println("BirdAdapter...");
// translate the methods appropriately birdAdapter.squeak(); }
bird.makeSound(); } }
}
BITS Pilani, Pilani Campus
Facade Pattern

• Just provide a unified and simplified interface to a


set of interfaces
• In a subsystem, it hides the complexities of the
subsystem from the client.
• Every Abstract Factory is a type of Facade.
• It shields the clients from the complexities of the
sub-system components.
• It promotes loose coupling between subsystems and
its clients.

BITS Pilani, Pilani Campus


Example

BITS Pilani, Pilani Campus


Basic Steps
//1 Create a MobileShop interface.
public interface MobileShop {
public void modelNo();
public void price();
}

//2 Create a Iphone implementation class that will implement Mobileshop interface.
public class Iphone implements MobileShop {
public void modelNo() {
System.out.println(" Iphone ");
} Similarly, create the classes for
public void price() { Samsung and Other Brands
System.out.println(" Rs 85000 ");
}
}
BITS Pilani, Pilani Campus
//3 Create a ShopKeeper concrete class that will use MobileShop interface.
public class ShopKeeper {
private MobileShop iphone;
private MobileShop samsung;
private MobileShop blackberry;

public ShopKeeper(){
iphone= new Iphone();
samsung=new Samsung();
blackberry=new Blackberry();
}
public void iphoneSale(){ iphone.modelNo(); iphone.price(); }
public void samsungSale(){ samsung.modelNo(); samsung.price(); }
public void blackberrySale(){ blackberry.modelNo(); blackberry.price(); }
}

BITS Pilani, Pilani Campus


switch (choice) {
//4 Create a client for buying the mobiles from MobileShop through ShopKeeper.
import java.io.BufferedReader; case 1:
import java.io.IOException; { sk.iphoneSale(); }
import java.io.InputStreamReader; break;
case 2:
public class FacadePatternClient { { sk.samsungSale(); }
private static int choice; break;
public static void main(String args[ ]) throws case 3:
NumberFormatException, IOException{ { sk.blackberrySale(); }
do{ break;
System.out.print("========= Mobile Shop ============ \n"); default: {
System.out.print(" 1. IPHONE. \n"); System.out.println(“Default");
System.out.print(" 2. SAMSUNG. \n"); }
System.out.print(" 3. BLACKBERRY. \n"); return; }
System.out.print(" 4. Exit. \n"); }while(choice!=4); } }
System.out.print("Enter your choice: ");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
choice=Integer.parseInt(br.readLine());
ShopKeeper sk=new ShopKeeper();
BITS Pilani, Pilani Campus
Example

BITS Pilani, Pilani Campus


Decorator Design Pattern

Decorator design pattern allows to add a property to an object in a dynamically, without


having to change the implementation of that object.
The decorator is considered as Structural design pattern, and follows the Open-
Closed Principle which provides a wrapper to the existing class.
The decorator design pattern uses abstract classes or interfaces with the composition
to implement the wrapper.
Steps:
• Create an interface, and create concrete classes implementing the same interface.
• Create an abstract decorator class implementing the above same interface.
• Create a concrete decorator class extending the above abstract decorator class.
• Now use the concrete decorator class created above to decorate interface objects.

BITS Pilani, Pilani Campus


Example: Decorator Pattern

BITS Pilani, Pilani Campus


Code

//1 Interface named Shape //3 Class 2


public interface Shape { // Abstract class
public abstract class ShapeDecorator implements Shape {
public void draw();
protected Shape decoratedShape;
} // Abstract class method
public ShapeDecorator(Shape decoratedShape)
// 2 {
public class Circle implements Shape { this.decoratedShape = decoratedShape;
}
public void draw()
// Method 2 - draw()
{ System.out.println("Shape: Circle"); // Outside abstract class
} public void draw() { decoratedShape.draw(); }
} }

BITS Pilani, Pilani Campus


Contd
// 4 Class 3
// Concrete class extending the abstract class
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape)
{
super(decoratedShape);
}
{
decoratedShape.draw();
setRedBorder(decoratedShape);
}

private void setRedBorder(Shape decoratedShape)


{
System.out.println("Border Color: Red");
}
}
BITS Pilani, Pilani Campus
Contd

public class DecoratorPatternDemo {


public static void main(String[ ] args)
{ Shape circle = new Circle();
Shape redCircle= new RedShapeDecorator(new Circle());
Shape redRectangle= new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}

BITS Pilani, Pilani Campus


Flyweight Design Pattern

Flyweight design pattern is used when we need to create a lot of Objects of a class.
Since every object consumes memory space that can be crucial for low memory
devices, such as mobile devices or embedded systems, flyweight design pattern
can be applied to reduce the load on memory by sharing objects.
Use sharing to support large numbers of fine-grained objects efficiently.
A flyweight object essentially has intrinsic and extrinsic attributes.
An intrinsic state attribute is stored/shared in the flyweight object, and it is
independent of flyweight’s context. We should make intrinsic states immutable.
An extrinsic state varies with flyweight’s context, which cannot be shared.
Client objects maintain the extrinsic state, and they need to pass this to a flyweight
object during object creation.

BITS Pilani, Pilani Campus


Major Components

The Flyweight Design Pattern involves the following key components:


Flyweight Interface : This is the interface that declares methods common to all
concrete flyweights. It may include methods for setting or getting intrinsic state.
Concrete Flyweight : This is the concrete implementation of the flyweight interface. It
contains the intrinsic state that is shared among multiple objects.
Unshared Concrete Flyweight : In some cases, not all flyweights can be shared. The
unshared concrete flyweight represents objects with unshareable intrinsic state.
Flyweight Factory: : This is responsible for managing flyweight objects and ensuring
that they are shared properly. It may include methods for creating or retrieving
flyweights.
Client : The client is responsible for using flyweights. It maintains the extrinsic state,
which is not shared among flyweights.

BITS Pilani, Pilani Campus


Example

BITS Pilani, Pilani Campus


Contd.

public class RailwayTicket implements Ticket {


private String type;
public interface Ticket { private int fare;
public void setName(String name); private String name;
public RailwayTicket(String type){
public void setFare(int fare); this.type = type; }
public void printTicket(); public void setName(String name){
this.name = name; }
} public void setFare(int fare){
this.fare = fare; }
public void printTicket(){
System.out.println("--------TICKET--------");
System.out.println("Name : "+ name + "\nTicket Type : "
+ type + "\nFare : " + fare); }
}

BITS Pilani, Pilani Campus


Contd.
import java.util.Map;
import java.util.HashMap;
public class TicketFactory {
private static Map<String, Ticket> ticketMap = new HashMap<String, Ticket>();
public static Ticket getTicket(String type, String name, int fare){
Ticket ticket;
if(ticketMap.containsKey(type)){
ticket = ticketMap.get(type);
} else {
ticket = new RailwayTicket(type);
ticketMap.put(type, ticket);
}
ticket.setName(name);
ticket.setFare(fare);
return ticket;
}
}
BITS Pilani, Pilani Campus
Contd.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class TicketBookingSystem {


public static void main(String args[ ]) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Ticket ticket;
for(int i=0; i < 5; i++){
System.out.println("Enter ticket type, Name and Fare");
String[ ] stringList = br.readLine().split(" ");
ticket = TicketFactory.getTicket(stringList[0], stringList[1], Integer.parseInt(stringList[2]));
ticket.printTicket();
}
}
}

BITS Pilani, Pilani Campus


Proxy Design Pattern

In proxy pattern, a class represents functionality of another class. This type of


design pattern comes under structural pattern.
In proxy pattern, we create object having original object to interface its functionality
to outer world.
Create an Image interface and concrete classes implementing the Image interface.
ProxyImage is a proxy class to reduce memory footprint of RealImage object
loading.
ProxyPatternDemo, our demo class, will use ProxyImage to get an Image object to
load and display as it needs.

BITS Pilani, Pilani Campus


Example

BITS Pilani, Pilani Campus


public interface Image {
void display();
}

public class RealImage implements Image {


private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
BITS Pilani, Pilani Campus
Contd.
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public class ProxyPatternDemo {
public ProxyImage(String fileName){ public static void main(String[] args) {
this.fileName = fileName; Image image = new ProxyImage("test_10mb.jpg");
} image.display();
System.out.println("");
public void display() { image.display();
if(realImage == null){ }
}
realImage = new RealImage(fileName);
}
realImage.display();
}
}
BITS Pilani, Pilani Campus
BITS Pilani
Pilani Campus

Behavioral Design Patterns in Java


(Module- 10c)
Observer Pattern

An Observer Pattern says that "just define a one-to-one dependency so that


when one object changes state, all its dependents are notified and updated
automatically".
The observer pattern is also known as Dependents or Publish-Subscribe.
It describes the coupling between the objects and the observer.
It provides the support for broadcast-type communication.

BITS Pilani, Pilani Campus


Example

BITS Pilani, Pilani Campus


Contd..

import java.util.Observable;
import java.util.Observer;

public class ResponseHandler1 implements Observer {


private String resp;
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
resp = (String) arg;
System.out.println("\nReceived Response: " + resp );
}
}
}// End of the ResponseHandler1 interface.
BITS Pilani, Pilani Campus
Contd..

import java.util.Observable;
import java.util.Observer;

public class ResponseHandler2 implements Observer {


private String resp;
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
resp = (String) arg;
System.out.println("\nReceived Response: " + resp );
}
}
}// End of the ResponseHandler2 interface.
BITS Pilani, Pilani Campus
Contd..
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
public class EventSource extends Observable implements Runnable {
public void run() {
try {
final InputStreamReader isr = new InputStreamReader(System.in);
final BufferedReader br = new BufferedReader(isr);
while (true) {
String response = br.readLine();
setChanged();
notifyObservers(response); }
}
catch (IOException e) { e.printStackTrace(); }
}
}// End of the Eventsource class.
BITS Pilani, Pilani Campus
State Design pattern

State pattern is to allow the object for changing its behavior without changing
its class.

Context class has an associated State which is going to


change during program execution.
Our context is going to delegate the behavior to the
state implementation.
In other words, all incoming requests will be handled by
the concrete implementation of the state.
Logic is separated and adding new states is simple.
It comes down to adding another State implementation if
needed.

Improves Cohesion since state-specific behaviors are


aggregated into the ConcreteState classes, which are
placed in one location in the code block.

BITS Pilani, Pilani Campus


Example

public interface State {


public void doAction(Context context);
}

public class StartState implements State {

public void doAction(Context context) {


System.out.println("Player is in start state");
context.setState(this);
}
public String toString(){
return "Start State";
}
}

BITS Pilani, Pilani Campus


Contd..

public class StopState implements State {


public void doAction(Context context) { public class Context {
private State state;
System.out.println("Player is in stop state");
public Context(){
context.setState(this); state = null;
} }
public String toString(){ public void setState(State state){
return "Stop State"; this.state = state;
}
}
public State getState(){
} return state;
}
}
BITS Pilani, Pilani Campus
Contd..
public class StatePatternDemo {
public static void main(String[] args) {
Context context = new Context();

StartState startState = new StartState();


startState.doAction(context);

System.out.println(context.getState().toString());

StopState stopState = new StopState();


stopState.doAction(context);

System.out.println(context.getState().toString());
}
}

BITS Pilani, Pilani Campus


Exercise: Aircraft-State

BITS Pilani, Pilani Campus


Mediator Design Pattern

Mediator: defines the interface for communication between colleague objects.


ConcreteMediator: It implements the mediator interface and coordinates
communication between colleague objects.
Colleague: It defines the interface for communication with other colleagues
ConcreteColleague: It implements the colleague interface and communicates
with other colleagues through its mediator.

The intent of the Mediator Pattern is to reduce


the complexity and dependencies between
tightly coupled objects communicating directly
with one another.
Design the system in such a way that
components are loosely coupled and reusable.

BITS Pilani, Pilani Campus


Example: Mediator Pattern

•ApnaChatroom: defines the interface for


interacting with participants.
•ApnaChatroomImpl: implements the
operations defined by Chatroom interface.
The operations are managing the
interactions between the objects: when
one participant sends a message, the
message is sent to other participants.
•Participant: defines an interface for the
users involved in chatting.
•User1, User2, ...UserN: implements
Participant interface.
• the participant can be a number of users
involved in chatting. But each Participant
will keep only a reference to the
ApnaChatRoom.

BITS Pilani, Pilani Campus


Contd…

public interface ApnaChatRoom {


public void showMsg(String msg, Participant p); }

public class ApnaChatRoomImpl implements ApnaChatRoom{


//get current date time
DateFormat dateFormat = new SimpleDateFormat("E dd-MM-yyyy hh:mm a");
Date date = new Date();
public void showMsg(String msg, Participant p) {
System.out.println(p.getName()+"'gets message: "+msg);
System.out.println("\t\t\t\t"+"["+dateFormat.format(date).toString()+"]");
}
}

BITS Pilani, Pilani Campus


Contd..

public abstract class Participant {


public abstract void sendMsg(String msg);
public class User1 extends Participant {
public abstract void setname(String name); private String name;
public abstract String getName(); private ApnaChatRoom chat;
public void sendMsg(String msg) {
}
chat.showMsg(msg,this);
}
public void setname(String name) {
this.name=name;
}
public String getName() {
return name; }
public User1(ApnaChatRoom chat){
this.chat=chat;
}
}

BITS Pilani, Pilani Campus


Contd..

public class MediatorPatternDemo {


public static void main(String args[])
{ ApnaChatRoom chat = new ApnaChatRoomImpl();
User1 u1=new User1(chat);
u1.setname("Aditya ");
u1.sendMsg("Hi Rohit! how are you? What about Compre?");

User2 u2=new User2(chat);


u2.setname("Rohit");
u2.sendMsg("I am Fine! How are you, Aditya? Going Slow..");
}

BITS Pilani, Pilani Campus


BITS Pilani, Pilani Campus
BITS Pilani
Pilani Campus

You might also like