Friday, December 11, 2015

Don't waste memory, Flyweight pattern

Take a look to this class.

public class Car {
private String engine;
private String color;
private long frameNumber;
public Car(long frameNumber, String engine, String color) {
this.engine = engine;
this.color = color;
this.frameNumber = frameNumber;
}
public String getEngine() {
return engine;
}
public String getColor() {
return color;
}
public long getFrameNumber() {
return frameNumber;
}
}
view raw MyCoolCar.java hosted with ❤ by GitHub
It looks like a regular POJO. And you are right, it's regular POJO, until here all it's ok.

Now, imagine your main program needs to instantiate our class Car 10 times. Then, the java heap memory will look like something like that.


What if I tell you that there are only two types of engines and two different colors ? Do you think that the memory allocation can be optimized to something that looks like the following picture ?


The answer is yes, with the Flyweight pattern. First of all, we have to design our light car with the common attributes.

public class LightCar {
private String engine;
private String color;
public LightCar(String engine, String color) {
this.engine = engine;
this.color = color;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
view raw LightCar.java hosted with ❤ by GitHub
After that, the next step is the container which contains all different types of light cars. It shall contain 4 different car types (2 engines x 2 colors).

public class LightCarContainer {
private static HashMap<String,LightCar> lightCars = new HashMap<String, LightCar>();
public static LightCar getLightCar(String engine, String color) {
String key = engine + color;
if (!lightCars.containsKey(key)) {
lightCars.put(key, new LightCar(engine,color));
}
return lightCars.get(key);
}
}
Then our Car class looks like something like that (pay attention to the new interface created Car and the delegation through LightCar).

public class CarFlyWeight implements Car {
private long frameNumber;
private LightCar lightCar;
public CarFlyWeight(long frameNumber, LightCar lightCar) {
this.frameNumber = frameNumber;
this.lightCar = lightCar;
}
@Override
public String getEngine() {
return lightCar.getEngine();
}
@Override
public String getColor() {
return lightCar.getColor();
}
@Override
public long getFrameNumber() {
return frameNumber;
}
}

And finally, our Factory to create cars.

public class CarFactory {
Car create(long frameNumber, String engine, String color) {
return new CarFlyWeight(frameNumber, LightCarContainer.getLightCar(engine, color));
}
}

I think this is a great pattern, sometimes forgotten ;) .

You can see the original article at www.arquitecturajava.com

No comments:

Post a Comment