Card 03/ 08
Flyweight Template in Python, Java and TypeScript
A factory that returns the same object for the same key, and a count of objects made.
The Flyweight template is the pattern in its pure form, with the participant names from the class diagram. Four placements of two kinds of tree are drawn through a factory, and the output counts the flyweights the factory made and checks that two requests for one key return the same object. The steps add each participant in Python, and the tabs give the complete program in three languages, each with its output.
Building the template one participant at a time
Flyweight
Holds the intrinsic state and takes the extrinsic state as an argument.
class Flyweight:
def __init__(self, intrinsic: str) -> None:
self._intrinsic = intrinsic
def operation(self, extrinsic: str) -> str:
return f"{self._intrinsic} at {extrinsic}"Factory
Creates a flyweight for a key once, and returns the stored one after that.
class FlyweightFactory:
def get(self, key: str) -> Flyweight:
if key not in self._pool:
self._pool[key] = Flyweight(key)
return self._pool[key]Client
Holds the extrinsic state, the positions, and passes it in.
for key, position in placements:
print(factory.get(key).operation(position))The complete template
class Flyweight:
def __init__(self, intrinsic: str) -> None:
self._intrinsic = intrinsic
def operation(self, extrinsic: str) -> str:
return f"{self._intrinsic} at {extrinsic}"
class FlyweightFactory:
def __init__(self) -> None:
self._pool: dict[str, Flyweight] = {}
def get(self, key: str) -> Flyweight:
if key not in self._pool:
self._pool[key] = Flyweight(key)
return self._pool[key]
def count(self) -> int:
return len(self._pool)
factory = FlyweightFactory()
placements = [("oak", "1,1"), ("pine", "2,5"), ("oak", "3,8"), ("oak", "9,2")]
for key, position in placements:
print(factory.get(key).operation(position))
print(f"placements: {len(placements)}, flyweights: {factory.count()}")
print(f"same object: {factory.get('oak') is factory.get('oak')}")oak at 1,1
pine at 2,5
oak at 3,8
oak at 9,2
placements: 4, flyweights: 2
same object: Trueimport java.util.HashMap;
import java.util.Map;
public class FlTemplate {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
String[][] placements = {{"oak", "1,1"}, {"pine", "2,5"}, {"oak", "3,8"}, {"oak", "9,2"}};
for (String[] placement : placements) {
System.out.println(factory.get(placement[0]).operation(placement[1]));
}
System.out.println("placements: " + placements.length + ", flyweights: " + factory.count());
System.out.println("same object: " + (factory.get("oak") == factory.get("oak")));
}
}
final class Flyweight {
private final String intrinsic;
Flyweight(String intrinsic) {
this.intrinsic = intrinsic;
}
String operation(String extrinsic) {
return intrinsic + " at " + extrinsic;
}
}
class FlyweightFactory {
private final Map<String, Flyweight> pool = new HashMap<>();
Flyweight get(String key) {
return pool.computeIfAbsent(key, Flyweight::new);
}
int count() {
return pool.size();
}
}oak at 1,1
pine at 2,5
oak at 3,8
oak at 9,2
placements: 4, flyweights: 2
same object: trueclass Flyweight {
constructor(private readonly intrinsic: string) {}
operation(extrinsic: string): string {
return `${this.intrinsic} at ${extrinsic}`;
}
}
class FlyweightFactory {
private readonly pool = new Map<string, Flyweight>();
get(key: string): Flyweight {
let flyweight = this.pool.get(key);
if (flyweight === undefined) {
flyweight = new Flyweight(key);
this.pool.set(key, flyweight);
}
return flyweight;
}
count(): number {
return this.pool.size;
}
}
const factory = new FlyweightFactory();
const placements: [string, string][] = [["oak", "1,1"], ["pine", "2,5"], ["oak", "3,8"], ["oak", "9,2"]];
for (const [key, position] of placements) {
console.log(factory.get(key).operation(position));
}
console.log(`placements: ${placements.length}, flyweights: ${factory.count()}`);
console.log(`same object: ${factory.get("oak") === factory.get("oak")}`);oak at 1,1
pine at 2,5
oak at 3,8
oak at 9,2
placements: 4, flyweights: 2
same object: trueFour placements needed two flyweights, and the last line confirms that the factory returned one object for both requests for oak. The positions never entered a flyweight; they stayed in the client's list and were passed in. With a million placements of four species, the factory would still hold four objects.
← → move through sections and cards