Skip to content

Instantly share code, notes, and snippets.

@KevinJones
Created April 24, 2014 18:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KevinJones/11264481 to your computer and use it in GitHub Desktop.
Save KevinJones/11264481 to your computer and use it in GitHub Desktop.
Multiple Singletons Example
// Three parts:
// 1. an enum with N values (or N+1 if you include a "None")
// 2. N enumerated singleton instances implementing a common interface. These provide information associated with each enum value in one place.
// 3. a static class allowing callers to access each enumerated singleton instance by passing in the corresponding enum value, creating it if necessary.
// Part 1
public enum Biome
{
Desert = 1,
Snow = 1 << 1,
Mountain = 1 << 2,
Plains = 1 << 3,
Forest = 1 << 4
}
// Part 2
public interface IBiomeInfo
{
// basics
public Biome EnumValue { get; }
public int Value { get; }
public string Name { get; }
// examples of related information
public Color ReferenceColor { get; }
public List<string> EnemyNames{ get; }
}
// you can implement this interface in a new class, like this:
public class DesertBiomeInfo : IBiomeInfo
{
public Biome EnumValue { get { return Biome.Desert; } }
public int Value { get { return (int)EnumValue; } }
public string Name { get { return "Desert"; } }
public Color ReferenceColor { get { return Color.Yellow; } }
private List<string> enemyNames = new List<string>("Deep Creeper", "Tacky Cactus", "Scorchion");
public List<string> EnemyNames { get { return enemyNames; } }
}
// or you can satisfy it with a less concrete class, and supply its data in the constructor via a factory method:
public class CustomBiomeInfo : IBiomeInfo
{
public Biome EnumValue { get; set; }
public int Value { get { return (int)EnumValue; } }
public string Name { get { return EnumValue.GetType().ToString(); } }
public Color ReferenceColor { get; set; }
public List<string> EnemyNames { get; set; }
public CustomBiomeInfo(Biome _enumValue, Color _refColor, List<string> _enemyNames)
{
EnumValue = _enumValue;
ReferenceColor = _refColor;
EnemyNames = _enemyNames;
}
}
// this example mixes CustomBiomeInfo with the immutable DesertBiomeInfo for demonstration purposes. In reality we'd probably stick to one approach or the other.
// Part 3
// This static "accessor" class is basically a memoized factory. Holds one instance per enum value.
public static class BiomeAccessor
{
private static Dictionary<Biome, IBiomeInfo> biomeInfoDict;
public static IBiomeInfo GetBiomeInfo(Biome _biome)
{
// I can't look up the proper dictionary syntax right now, so please forgive me. ;)
if (!biomeInfoDict.ContainsKey(_biome))
{
biomeInfoDict.Add(_biome, createBiomeInfo(_biome));
}
return biomeInfoDict[_biome];
}
// the factory method, or "the only switch statement you'll need"
private static IBiomeInfo createBiomeInfo(Biome _biome)
{
switch(_biome)
{
case Biome.Desert:
return new DesertBiomeInfo();
case Biome.Snow:
return new CustomBiomeInfo(Biome.Snow, Color.White, new List<string>("Frost Bunny", "Aurora"));
// and so on for the other Biome enum values
default:
throw new BiomeNotFoundException();
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment