+The letters and positions differ; their style is shared. Singleton limits a class to one instance; this pool shares one object per font-and-size combination. This pool is used on one thread.
TypeScript example
Glyphs share font and size, but retain their own letter and position. Separating those values permits style reuse without mixing one placement’s data into another.
// Put only immutable, shareable values in the style object.
class GlyphStyle {
constructor(readonly font: string, readonly size: number) { Object.freeze(this); }
}
type PlacedGlyph = Readonly<{ letter: string; x: number; style: GlyphStyle }>;
// Reuse the object for the same key instead of constructing a style per placement.
class StylePool {
private readonly fonts = new Map<string, Map<number, GlyphStyle>>();
get(font: string, size: number): GlyphStyle {
let sizes = this.fonts.get(font);
if (!sizes) { sizes = new Map(); this.fonts.set(font, sizes); }
let style = sizes.get(size);
if (!style) { style = new GlyphStyle(font, size); sizes.set(size, style); }
return style;
}
get count(): number { return [...this.fonts.values()].reduce((n, sizes) => n + sizes.size, 0); }
}
const pool = new StylePool();
const letters: PlacedGlyph[] = [
{ letter: "A", x: 0, style: pool.get("Serif", 16) },
{ letter: "B", x: 20, style: pool.get("Serif", 16) },
];
for (const glyph of letters) console.log(glyph.letter + "@" + glyph.x);
console.log("styles: " + pool.count);
A@0
B@20
styles: 1
Object.freeze keeps the shared style immutable, and the pool looks up both font and size. Retention and size limits are separate policies omitted from this example.