Created
April 24, 2014 18:25
-
-
Save KevinJones/11264481 to your computer and use it in GitHub Desktop.
Multiple Singletons Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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