Problem
The definition of flyweight pattern:
Flyweight design pattern uses sharing to support large numbers of objects that have part of their internal state common and other parts of state can vary.
Please let me know whether I implemented this pattern correctly. I also want to know whether the map structure is always needed when implement this pattern. Anything related to the pattern is also welcomed.
Bike
: Define the interface for clients to ride the bike at the speed they want.Motorcycle
: Implementation ofBike
. Has internal stateBikeType
, which is decided when created.BikeType
: Two types of bikes- Scooter
- Sports bike
FlyweightFactory
: The bike rental store. I chose this name to make it clear of the role it plays in the flyweight pattern.- Factory is a singleton, only one factory.
- Choose the
BikeType
and get the bike.
Bike.java
public interface Bike
{
// speed is external state.
public void rideBike(int speed);
}
Motorcycle.java
public class Motorcycle implements Bike
{
// BikeType is internal state.
private BikeType bikeType;
public Motorcycle(BikeType bikeType) {
this.bikeType = bikeType;
}
@Override
public void rideBike(int speed) {
System.out.format("Riding %s at speed %d mps%n",
getBikeType().getTypeName(),
speed);
}
//
private BikeType getBikeType() {
return this.bikeType;
}
}
BikeType.java
public enum BikeType
{
SPORTS("Sports Bike"), SCOOTER("Scooter");
private String typeName;
private BikeType(String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return this.typeName;
}
}
FlyweightFactory.java
I implemented the flyweight rental store with singleton pattern:
public class FlyweightFactory
{
// static fields & methods
private static volatile FlyweightFactory factory;
public static FlyweightFactory getFactory() {
if (factory == null) {
synchronized (FlyweightFactory.class) {
if (factory == null) {
factory = new FlyweightFactory();
}
}
}
return factory;
}
// Instance fields & methods
private Map<BikeType, Bike> bikes;
private FlyweightFactory() {
this.bikes = new HashMap<>();
}
public Bike getBike(BikeType bikeType) {
Bike bikeReturn = getBikes().get(bikeType);
if (bikeReturn == null) {
bikeReturn = new Motorcycle(bikeType);
getBikes().put(bikeType, bikeReturn);
}
return bikeReturn;
}
// setters & getters
private Map<BikeType, Bike> getBikes() {
return this.bikes;
}
}
App.java
Example program to test the flyweight factory works well:
public class App
{
public static void main(String[] args) {
FlyweightFactory ff = FlyweightFactory.getFactory();
Bike sportBike = ff.getBike(BikeType.SPORTS);
System.out.println(sportBike);
System.out.println(ff.getBike(BikeType.SPORTS));
sportBike.rideBike(20);
System.out.println(" --- ");
Bike scooter = ff.getBike(BikeType.SCOOTER);
System.out.println(scooter);
scooter.rideBike(30);
}
}
Output:
Motorcycle@7c17831
Motorcycle@7c17831
Riding Sports Bike at speed 20 mps
---
Motorcycle@26cf402f
Riding Scooter at speed 30 mps
Solution
The flyweight pattern exists to minimize memory usage. I don’t think it is what you need here. At least, wha you have done looks like strategy.
But because your are asking about the flyweight let me try to explain a good usage of it. The goal of the flyweight is to reduce memory usage. The idea is to have something like a date stamp that you can reuse to print differents dates. You take your stamp, roll the numbers to have the expected date, apply it and then forgot or use the same for another date.
public class DateStamp {
private int year, month, day;
// setters
public void apply() {
System.out.printf("%1$d/%2$d/%3$d", year, month, day);
}
}
// ..
DateStamp stamp = new DateStamp();
stamp.set..
stamp.apply();
stamp.set..
stamp.apply();
In many systems today, this pattern is rarely used due to the hughe amount of availables memory. Creating new instances is almost no cost.
But when the creation of a new instance can be costly or when you have hundreds instances of the same type at the same time it can be interesting to use it.
About your code and implementation of the factory, there is nothing wrong with the map. It is the best structure to keep a “relation” between two things.
Another implementation, would be to use an abstract Bike
as explained by BKSpurgeon.