Sample Code
Java
public enum FontEffect {
BOLD, ITALIC, SUPERSCRIPT, SUBSCRIPT, STRIKETHROUGH
}
public final class FontData {
/**
* A weak hash map will drop unused references to FontData.
*/
private static final WeakHashMap<FontData, FontData>flyweightData = new WeakHashMap<FontData, FontData>();
private final int pointSize;
private final String fontFace;
private final Color color;
private final Set<FontEffect> effects;
private FontData(int pointSize, String fontFace, Color color, EnumSet<FontEffect> effects) {
this.pointSize = pointSize;
this.fontFace = fontFace;
this.color = color;
this.effects = Collections.unmodifiableSet(effects);
}
public static FontData create(int pointSize, String fontFace, Color color, FontEffect... effects) {
EnumSet<FontEffect> effectsSet = EnumSet.noneOf(FontEffect.class);
for (FontEffect fontEffect : effects) {
effectsSet.add(fontEffect);
}
// We are unconcerned with object creation cost, we are reducing overall memory consumption
FontData data = new FontData(pointSize, fontFace, color, effectsSet);
if (!flyweightData.containsKey(data)) {
flyweightData.put(data, data);
}
// return the single immutable copy with the given values
return flyweightData.get(data);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FontData) {
if (obj == this) {
return true;
}
FontData other = (FontData) obj;
return other.pointSize == pointSize && other.fontFace.equals(fontFace)
&& other.color.equals(color) && other.effects.equals(effects);
}
return false;
}
@Override
public int hashCode() {
return (pointSize * 37 + effects.hashCode() * 13) * fontFace.hashCode();
}
// Getters for the font data, but no setters. FontData is immutable.
}
C#
using System.Collections;
using System.Collections.Generic;
using System;
class GraphicChar {
char c;
string fontFace;
public GraphicChar(char c, string fontFace) { this.c = c; this.fontFace = fontFace; }
public static void printAtPosition(GraphicChar c, int x, int y) {
Console.WriteLine("Printing '" + c.c + "' in '{1}' at position {2}:{3}.", c.c, c.fontFace, x, y);
}
}
class GraphicCharFactory {
Hashtable pool = new Hashtable(); // the Flyweights
public int getNum() { return pool.Count; }
public GraphicChar get(char c, string fontFace) {
GraphicChar gc;
string key = c.ToString() + fontFace;
if ((gc = (GraphicChar)pool[key]) == null) {
gc = new GraphicChar(c, fontFace);
pool.Add(key, gc);
}
return gc;
}
}
class FlyWeightExample {
public static void Main(string[] args) {
GraphicCharFactory cf = new GraphicCharFactory();
// Compose the text by storing the characters as objects.
List<GraphicChar> text = new List<GraphicChar>();
text.Add(cf.get('H', "Arial")); // 'H' and "Arial" are called intrinsic information
text.Add(cf.get('e', "Arial")); // because it is stored in the object itself.
text.Add(cf.get('l', "Arial"));
text.Add(cf.get('l', "Arial"));
text.Add(cf.get('o', "Times"));
// See how the Flyweight approach is beginning to save space:
Console.WriteLine("CharFactory created only {0} objects for {1} characters.", cf.getNum(), text.Count);
int x=0, y=0;
foreach (GraphicChar c in text) { // Passing position as extrinsic information to the objects,
GraphicChar.printAtPosition(c, x++, y); // as a top-left 'A' is not different to a top-right one.
}
}
}