開放閉鎖の原則(Open/Closed Principle)
SOLID原則のひとつ。
開放(Open) | 拡張に対して開いている。 |
---|---|
閉鎖(Closed) | 修正に対して閉じている。 |
新しく機能を追加するとき、既存のコードを変更せずにあたらしいコードを追加するだけで済むようにする。
格闘家を例にとる
一般的に格闘技には階級がある。
選手は規定の体重以内で計量をパスしなければならない。
public enum WeightClass
{
Heavy,
Light
}
public class Fighter
{
public WeightClass WeightClass;
public string Name { get; private set; }
public double Weight { get; set; }
public Fighter(string name, WeightClass weightClass)
{
this.Name = name;
this.WeightClass = weightClass;
}
public bool WeightIn()
{
switch (this.WeightClass)
{
case WeightClass.Light:
return this.Weight <= 70.3;
default:
return this.Weight <= 120.2;
}
}
}
階級を増やす
競技人口の増加により、2階級のみでは競技性が損なわれるため、HeavyとLightの間にMiddleを増やしたい。
WeightClassにMiddleを増やすのは容易(拡張に対して開いている)だが、 WeightInに修正が発生(閉じていない)する。
解決策
格闘家を基底クラスとして、階級ごとに派生クラスを作成する。
public enum WeightClass
{
Heavy,
Middle,
Light
}
public abstract class Fighter
{
public WeightClass WeightClass;
public string Name { get; private set; }
public double Weight { get; set; }
public Fighter(string name, WeightClass weightClass)
{
this.Name = name;
this.WeightClass = weightClass;
}
public abstract bool WeightIn();
}
public class HeavyWeightFighter : Fighter
{
private static readonly double LIMIT = 120.2;
public HeavyWeightFighter(string name, WeightClass weightClass) : base(name, weightClass) { }
public override bool WeightIn() => this.Weight <= LIMIT;
}
public class MiddleWeightFighter : Fighter
{
private static readonly double LIMIT = 83.9;
public MiddleWeightFighter(string name, WeightClass weightClass) : base(name, weightClass) { }
public override bool WeightIn() => this.Weight <= LIMIT;
}
public class LightWeightFighter : Fighter
{
private static readonly double LIMIT = 70.3;
public LightWeightFighter(string name, WeightClass weightClass) : base(name, weightClass) { }
public override bool WeightIn() => this.Weight <= LIMIT;
}