Flyweight mode


Flyweight Pattern is mainly used to reduce the number of objects created to reduce memory usage and improve performance. This type of design pattern is a structural pattern, which provides a way to reduce the number of objects and thus improve the object structure required by the application.

Flyweight mode attempts to reuse existing objects of the same type, and if no matching object is found, a new object is created. We will demonstrate this pattern by creating 5 objects that draw 20 circles in different locations. Since there are only 5 colors available, the color property is used to check for an existing Circle object.

Introduction

Intent: Use sharing technology to effectively support a large number of fine-grained objects.

Main solution: When there are a large number of objects, it may cause memory overflow. We abstract the common parts. If there is the same business request, directly return the data already stored in the memory. Some objects are avoided from being recreated.

When to use: 1. There are a large number of objects in the system. 2. These objects consume a lot of memory. 3. Most of the status of these objects can be externalized. 4. These objects can be divided into many groups according to their intrinsic states. When extrinsic objects are removed from the objects, each group of objects can be replaced by an object. 5. The system does not rely on the identity of these objects, and these objects are indistinguishable.

How to solve: Use the unique identification code to judge. If there is one in the memory, return the object identified by the unique identification code.

Key code: Use HashMap to store these objects.

Application examples: 1. String in JAVA, if it exists, it will be returned. If not, a string will be created and stored in the string cache pool. 2. The data pool of the database.

Advantages: Greatly reduces the creation of objects, reduces system memory, and improves efficiency.

Disadvantages: Improves the responsibility of the system and requires the separation of external and internal states. Moreover, the external state has an inherent nature and should not change with changes in the internal state. Otherwise it will cause system chaos.

Usage scenarios: 1. The system has a large number of similar objects. 2. Scenarios that require a buffer pool.

Notes: 1. Pay attention to dividing external state and internal state, otherwise thread safety issues may occur. 2. These classes must be controlled by a factory object.

Implementation

We will create a Shape interface and an entity class Circle that implements the Shape interface. The next step is to define the factory class ShapeFactory.

ShapeFactory There is a HashMap of Circle, where the key name is the color of the Circle object. Whenever a request is received, a circle of a specific color is created. ShapeFactory checks the circle object in its HashMap and if a Circle object is found, it is returned, otherwise it is created and stored in a hashmap for subsequent use new object and returns the object to the client.

FlyWeightPatternDemo, our demo class uses ShapeFactory to obtain the Shape object. It will pass information (red / green / blue / black / white) to the ShapeFactory in order to get the color of the object it needs.

flyweight_pattern_uml_diagram.jpg

Step 1

Create an interface.

Shape.java

public interface Shape {
   void draw();
}

Step 2

Create an entity class that implements the interface.

Circle.java

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

Step 3

Create a factory to generate objects of entity classes based on given information.

ShapeFactory.java

import java.util.HashMap;

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

Step 4

Use this factory to obtain the object of the entity class by passing color information.

FlyweightPatternDemo.java

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();
      }
   }
   private static String getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
   private static int getRandomX() {
      return (int)(Math.random()*100 );
   }
   private static int getRandomY() {
      return (int)(Math.random()*100);
   }
}

Step 5

Verify the output.

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100