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