Flyweight Design Pattern

The Flyweight Design Pattern is used when we want to create large number of similar object. Instead of creating large numbers of similar objects, it reused the similar object created earlier. Creating large number of objects consumes memory resources and reduce the performance of your code, flyweight design pattern solves this problem by sharing similar objects.

In the flyweight pattern, segregating object properties into Intrinsic and Extrinsic state. Intrinsic states are things that are constant and stored inside of the objects. Extrinsic states are things that are the differences in objects and need to be calculated on the fly, they are moved outside of the objects and placed in client code. The object with intrinsic state is called flyweight object.

Flyweight design pattern comes under structural pattern as it provides ways to reduce number of objects and optimize performance.

Advantages of Flyweight Pattern

  • It reduces the number of objects created.
  • It reduce memory requirements and instantiation time and related costs.
  • One object of a class can provide many virtual instances.

When we should use Flyweight Pattern

  • When we want to create large number of similar objects having almost similar functionality. Instead of creating large number of instances of a class we can reuse already existing similar objects by storing them. IF no match found, then we will create a new object and store it for future reuse.
  • When we want to reduce the storage cost of large number of objects and improve performance.
  • When we can make object specific attributes external and can be computes on run-time.
  • When client doesn’t enforce unique objects.

Let’s take a real world example of ticket booking system. This system issues large number of tickets to passengers per day. Tickets can be of two types “ADULT” and “INFANT”. In ticket booking system, ticket objects doesn’t have much functionalities except printing itself. Passenger name and fare can vary depending on the ticket type. We can use flyweight design pattern in this scenario as every ticket of a particular type(let’s say adult) is almost similar except it’s extrinsic state(Name and fare) which can be passed to ticket object on runtime.

Implementation of Flyweight Design Pattern

We will define Ticket interface which contains the public method to set extrinsic properties(name and fare) of the ticket and printTicket method to enforce common ticket printing functionality.

FlyWeight_Pattern

Flyweight Design Pattern

Ticket.java
public interface Ticket {
    public void setName(String name);
    public void setFare(int fare);
    public void printTicket();
}

RailwayTicket is a concrete implementation of Ticket interface.

Flyweight Design Pattern 1

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

TicketFactory is a factory class to provide Railway tickets of different types. It stores one instance of various ticket types in a HashMap having ticket type as key. It exposes a ‘getTicket’ method to clients, which calls this method by passing the railway ticket fields. Inside this method, it first checks whether we already have an instance of requested ticket type. If present, it reuses it and sets the extrinsic attributes of tickets and returns it to client(TicketBookingSystem) other wise it creates a new instance of ticket and stores it in HashMap for future use.

Flyweight Design Pattern 2

TicketFactory.java
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;
    } 
}

TicketBookingSystem is the client of TicketFactory, which created large number of tickets on run time by calling getTicket method.

Flyweight Design Pattern 3

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

Output

Enter ticket type, Name and Fare
INFANT Jack 100
--------TICKET--------
Name : Jack
Ticket Type : INFANT
Fare : 100
Enter ticket type, Name and Fare
ADULT George 500
--------TICKET--------
Name : George
Ticket Type : ADULT
Fare : 500
Enter ticket type, Name and Fare
INFANT Adams 100
--------TICKET--------
Name : Adams
Ticket Type : INFANT
Fare : 100
Enter ticket type, Name and Fare
INFANT Julia 100
--------TICKET--------
Name : Julia
Ticket Type : INFANT
Fare : 100
Enter ticket type, Name and Fare
ADULT Rex 500
--------TICKET--------
Name : Rex
Ticket Type : ADULT
Fare : 500