I feel like I have an ok grasp on the design pattern, however I can't seem to get my head around one thing and it doesn't seem to be exactly explained in the resources I've looked at.
That question is, how is the data common, without the data being static, considering the objects are separate entities?
https://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm
In this example, I cannot figure out where the optimisation is occurring, as it looks as if the objects are just being created each time as normal.
Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
This code block seems like my best guess as the first line retrieves from the HashMap a circle with a certain colour, but this creates a new instance of a circle, with no lasting reference to the colour of the circle.
Therefore, unless I'm mistaken, there is no actual shared data, so I am unsure of how this provides benefits other than maybe during creation.
The ShapeFactory
in your linked example will create one Circle
per color:
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;
}
}
If no Circle
with a specified color exists, it will create a new Circle
object and store this instance in the circleMap
hashmap. If a Circle
with a specific color already exists, it will return the already existing instance from the circleMap
.
This is also explained in the text:
ShapeFactory has a HashMap of Circle having key as color of the Circle object. Whenever a request comes to create a circle of particular color to ShapeFactory, it checks the circle object in its HashMap, if object of Circle found, that object is returned otherwise a new object is created, stored in hashmap for future use, and returned to client.
This is also evident in the output shown in the tutorial:
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
Each colored Circle
is only created once, but modified many times.
I agree that the tutorial doesn't really show the benefit of a Flyweight though. The main point of the flyweight is to externalise shared state. The usual examples I know use character properties in a document.
Instead of having one Character
with position
, font
, size
and textDecoration
, you would externalize the latter three, thereby reducing the memory needed for each Character
instance:
This is some text.
In the line above, the individual characters would only need to store their position, but the formatting is the same, so that can be externalised to a single flyweight object.
This is some bold text.
In the line above, you'd have two flyweights. One for the regular text and another for the four bold character instances.