Project Technical Lead
Java design pattern: Flyweight
Today we will take a look at another Java design pattern from the structural patterns category – Flyweight. Design patterns in this category deal with class structure such as inheritance and composition.
What is the Flyweight design pattern?
Flyweight is a design pattern that is primarily used to reduce the number of objects created because it attempts to reuse existing objects with the same or similar properties at the class level, and only creates a new object when no matching object is found. This minimizes the amount of memory used for data shared between similar objects.
What problem does the Flyweight design pattern solve?
It solves the problem in applications that work with a large number of objects, which would take a lot of memory if stored separately, and the cost of creating them is not negligible. This pattern solves the problem by extracting common data and sharing it between objects, reducing the amount of memory required and making use of already created objects.
Example of Flyweight implementation in Java
We will now write a program to simulate a simple system for running a pizza restaurant, and we will demonstrate just using the Flyweight design pattern to efficiently share instances of pizza and minimize the number of objects created. The program creates a pizzeria, takes orders for different types of pizzas and serves them. It will consist of Pizza, Order and Pizzeria and Main classes.
Pizza.java
package designpatterns;
import java.util.HashMap;
import java.util.Map;
public class Pizza {
private static Map<String, Pizza> pizzaCache = new HashMap<>();
private String nazov;
private Pizza(String nazov) {
this.nazov = nazov;
}
public static Pizza intern(String nazov) {
pizzaCache.putIfAbsent(nazov, new Pizza(nazov));
return pizzaCache.get(nazov);
}
public static int pocetDruhov() {
return pizzaCache.size();
}
@Override
public String toString() {
return nazov;
}
}
The Pizza class represents a type of pizza and uses the Flyweight pattern to share instances of pizzas with the same name. It has an intern() method that creates a new pizza only if it doesn’t already exist, and a pocetDruhov() method that returns the number of different kinds of pizzas.
Objednavka.java
package designpatterns;
public class Objednavka {
private Pizza pizza;
private int cisloStolu;
private Objednavka(Pizza pizza, int cisloStolu) {
this.pizza = pizza;
this.cisloStolu = cisloStolu;
}
public static Objednavka create(String nazov, int cisloStolu) {
Pizza pizza = Pizza.intern(nazov);
return new Objednavka(pizza, cisloStolu);
}
@Override
public String toString() {
return "Posielam pizzu " + pizza + " na stol " + cisloStolu;
}
}
The Objednavka class represents a pizza order. Each order contains a link to a specific pizza and the table number where the pizza is to be delivered.
Pizzeria.java
package designpatterns;
public class Pizzeria {
private java.util.List<Objednavka> objednavky = new java.util.ArrayList<>();
public void prijatObjednavku(String druh, int cisloStolu) {
objednavky.add(Objednavka.create(druh, cisloStolu));
}
public void obsluzit() {
for (Objednavka order : objednavky) {
System.out.println(order);
}
}
public int pocetPrijatychObjednavok() {
return objednavky.size();
}
}
The Pizzeria class represents a pizzeria that accepts orders and provides methods for processing and listing orders. It also provides a method for obtaining the number of orders received.
Main.java
import designpatterns.Pizzeria;
import designpatterns.Pizza;
public class Main {
public static void main(String[] args) {
Pizzeria pizzeria = new Pizzeria();
pizzeria.prijatObjednavku("Hawai", 2);
pizzeria.prijatObjednavku("Quattro Formaggi", 1);
pizzeria.prijatObjednavku("Margherita", 1);
pizzeria.prijatObjednavku("Napoletana", 5);
pizzeria.prijatObjednavku("Hawai", 4);
pizzeria.prijatObjednavku("Quattro Formaggi", 3);
pizzeria.prijatObjednavku("Margherita", 3);
pizzeria.prijatObjednavku("Hawai", 3);
pizzeria.prijatObjednavku("Margherita", 6);
pizzeria.prijatObjednavku("Quattro Formaggi", 2);
pizzeria.obsluzit();
System.out.println();
System.out.println("Pocet prijatych objednavok: " + pizzeria.pocetPrijatychObjednavok());
System.out.println("Pocet pouzitych objektov typu pizza: " + Pizza.pocetDruhov());
}
}
In the main method, a pizzeria instance is created and then various pizza orders are created. All orders are served and finally the number of orders received and the number of Pizza objects used are listed. Thus, we have demonstrated the sharing of Pizza-type objects between disparate orders.
The output of this example is:
Summary
The Flyweight design pattern is used in situations where we need to cache and reuse object instances that are similar. It is mainly aimed at optimizing the overhead of object creation and their memory requirements.
We have prepared the files with the above example in the form of code that you can run directly in Java. Download the Java Flyweight code here.
If you’re a Java developer looking for work, check out our employee benefits and respond to our latest job offers.