クラスや構造体を作成する際のお手本ともなる基本的なデザイン・パターンは身近なところにある。
例えば Color構造体。
このColor構造体を妄想を含めてその構造を見てみる。
ユーザーに直接 new させない
new させないといってももちろんインスタンスを生成できないワケではなく、インスタンス生成するより簡単な方法を提供することで、new することの必要性をなくしている。
Color 構造体の場合、そのインスタンスを生成するには通常このように行う。
Color color1 = Color.FromArgb(0, 255, 255);
Color color2 = Color.FromKnownColor(KnownColor.Cyan);
Color color3 = Color.FromName("Cyan");
これらのstaticなメソッドを使用することでより簡単にインスタンスを生成することが出来るようになっている。
staticを上手く活用する
上記に挙げたインスタンスを生成するメソッドはstatic のため、インスタンスを生成すれば不可視になる。
インスタンスにとってこれらのメソッドは不要となるため、使用側、開発側どちらにとってもありがたいものとなる。
逆にインスタンスの生成によってR,G,Bなどのプロパティが可視となる。
このように、クラス(構造体)のstaticなメンバによってそのオブジェクトの言ってみれば"インスタンス生成工場"の面を見せ、生成されたインスタンスではそれらを不可視にして、必要なプロパティを保持するという二つの面を持ち合せている。
Color構造体の妄想コード
恐らくこのようになっているだろうという単なる妄想です。
シンプルにするため大分ハショってますが「大体こんな感じでは?」というものです。
『
xColor』として書いてます。
public struct xColor
{
private struct Rgb
{
byte red, green, blue;
public Rgb(byte r, byte g, byte b)
{
red = r; green = g; blue = b;
}
public byte R { get { return red; } }
public byte G { get { return green; } }
public byte B { get { return blue; } }
}
byte alpha, red, green, blue;
string name;
static Dictionary<KnownColor, Rgb> _rgbList = new Dictionary<KnownColor, Rgb>();
static xColor()
{
_rgbList.Add(KnownColor.Cyan, new Rgb(0, 255, 255));
_rgbList.Add(KnownColor.Yellow, new Rgb(255, 255, 0));
_rgbList.Add(KnownColor.Magenta, new Rgb(255, 0, 255));
_rgbList.Add(KnownColor.Control, new Rgb(204, 204, 204));
//...
}
public static xColor FromArgb(int a, int r, int g, int b)
{
return xColorFactory((byte)a, (byte)r, (byte)g, (byte)b, string.Empty);
}
public static xColor FromKnownColor(KnownColor kc)
{
return RgbSelecter(kc);
}
public static xColor FromName(string name)
{
foreach (KnownColor c in Enum.GetValues(typeof(KnownColor)))
{
if(name.ToUpper() == c.ToString().ToUpper()) return RgbSelecter(c);
}
throw new NotSupportedException("err");
}
private static xColor xColorFactory(byte a, byte r, byte g, byte b, string name)
{
xColor xc = new xColor();
xc.alpha = a;
xc.red = r;
xc.green = g;
xc.blue = b;
xc.name = name;
return xc;
}
private static xColor RgbSelecter(KnownColor kc)
{
try
{
Rgb rgb = _rgbList[kc];
return xColorFactory(255, rgb.R, rgb.G, rgb.B, kc.ToString());
}
catch (KeyNotFoundException ex)
{
throw new KeyNotFoundException(ex.Message);
}
}
public string Name{ get { return name; }}
public byte A{ get { return alpha; }}
public byte R{ get { return red; }}
public byte G{ get { return green; }}
public byte B{ get { return blue; }}
public static xColor Cyan { get { return RgbSelecter(KnownColor.Cyan); } }
public static xColor Yellow { get { return RgbSelecter(KnownColor.Yellow); } }
public static xColor Magenta { get { return RgbSelecter(KnownColor.Magenta); } }
}
これを使用した結果は擬似的に Color 構造体と同じになるよう作っているので使用例までは出さないが、もちろん Color 構造体の代わりになるワケではない。
少し言葉を付け加えるなら、
なぜ Color 構造体のプロパティにはない『Color.Control』のインスタンスを生成できるのか?
一つは KnownColor にあること。
もう一つは上記コードで言うところの『RgbSelecter』メソッドでサポートすれば可能となる話である。
以上、妄想が入り混じったお話でした。