Lab
Flyweight
// Shared: how every marker of one kind looks. Nothing changes it.
type MarkerStyle = Readonly<{ glyph: string; size: string }>;
// Local: what belongs to one place on the map.
type Place = {
id: number; x: number; y: number; style: MarkerStyle; selected: boolean;
};
const glyphs: Record<string, string> = { hospital: 'H', school: 'S', park: 'P' };
// The flyweight factory: one style per kind of marker, made on first request.
class StyleBook {
private styles = new Map<string, MarkerStyle>();
get(category: string, size: string): MarkerStyle {
const key = `${category}/${size}`;
let style = this.styles.get(key);
if (!style) {
style = Object.freeze({ glyph: glyphs[category], size });
this.styles.set(key, style);
}
return style;
}
get count(): number {
return this.styles.size;
}
}
// One map, one book. Place 3 is the trauma centre, drawn large.
const place = (id: number, x: number, y: number, style: MarkerStyle): Place =>
({ id, x, y, style, selected: false });
const book = new StyleBook();
const places = [
place(1, 12, 40, book.get('hospital', 'small')),
place(2, 30, 18, book.get('school', 'small')),
place(3, 47, 62, book.get('hospital', 'large')),
place(4, 65, 25, book.get('hospital', 'small')),
];
// Selecting a place changes that place, never the style it shares.
function selectPlace(places: Place[], id: number) {
for (const place of places) place.selected = place.id === id;
}
selectPlace(places, 4);
const shared = places[0].style === places[3].style;
const styles = book.count;
for (const p of places) {
const mark = p.selected ? ' (selected)' : '';
const { glyph, size } = p.style;
console.log(`#${p.id} ${glyph} ${size} at ${p.x},${p.y}${mark}`);
}
console.log(`${places.length} places, ${styles} styles`);
console.log(`#1 and #4 share one style: ${shared}`);
TODO
Visual to come