第11天:用策略模式代替switch
今天的重构很有意思,旧的代码是根据参数State来调用三个不同的方法,获取三个地方的装运量
代码如下:
public class ClientCode
{
public decimal CalculateShipping()
{
ShippingInfo shippingInfo = new ShippingInfo();
return shippingInfo.CalculateShippingAmount(State.Alaska);
}
}
public enum State
{
Alaska,
NewYork,
Florida
}
public class ShippingInfo
{
public decimal CalculateShippingAmount(State shipToState)
{
switch (shipToState)
{
case State.Alaska:
return GetAlaskaShippingAmount();
case State.NewYork:
return GetNewYorkShippingAmount();
case State.Florida:
return GetFloridaShippingAmount();
default:
return 0m;
}
}
private decimal GetAlaskaShippingAmount()
{
return 15m;
}
private decimal GetNewYorkShippingAmount()
{
return 10m;
}
private decimal GetFloridaShippingAmount()
{
return 3m;
}
}
如果我们现在要加一个Chicago的条件,那么不得不修改整个ShippingInfo
重构后用策略模式,对每一个条件加一个类,并且实现同一个接口,以后如果希望添加新的条件,只需添加新的实现类就可以了,实现对修改关闭,对扩展开放
重构后的代码如下
public class ClientCode
{
public decimal CalculateShipping()
{
ShippingInfo shippingInfo = new ShippingInfo();
return shippingInfo.CalculateShippingAmount(State.Alaska);
}
}
public enum State
{
Alaska,
NewYork,
Florida
}
public class ShippingInfo
{
private IDictionary<State, IShippingCalculation> ShippingCalculations
{ get; set; }
public ShippingInfo()
{
ShippingCalculations = new Dictionary<State, IShippingCalculation>{
{ State.Alaska, new AlaskShippingCalculation() },
{ State.NewYork, new NewYorkShippingCalculation() },
{ State.Florida, new FloridaShippingCalculation() }};
}
public decimal CalculateShippingAmount(State shipToState)
{
return ShippingCalculations[shipToState].Calculate();
}
}
public interface IShippingCalculation
{
decimal Calculate();
}
public class AlaskShippingCalculation : IShippingCalculation
{
public decimal Calculate()
{
return 15m;
}
}
public class NewYorkShippingCalculation : IShippingCalculation
{
public decimal Calculate()
{
return 10m;
}
}
public class FloridaShippingCalculation : IShippingCalculation
{
public decimal Calculate()
{
return 3m;
}
}
故事还没完,书的作者又进行了如下的重构,今天没有弄明白,先记录下来
public interface IShippingInfo
{
decimal CalculateShippingAmount(State state);
}
public class ClientCode
{
[Inject]
public IShippingInfo ShippingInfo { get; set; }
public decimal CalculateShipping()
{
return ShippingInfo.CalculateShippingAmount(State.Alaska);
}
}
public enum State
{
Alaska,
NewYork,
Florida
}
public class ShippingInfo : IShippingInfo
{
private IDictionary<State, IShippingCalculation> ShippingCalculations
{ get; set; }
public ShippingInfo(IEnumerable<IShippingCalculation> shippingCalculations)
{
ShippingCalculations = shippingCalculations.ToDictionary(
calc => calc.State);
}
public decimal CalculateShippingAmount(State shipToState)
{
return ShippingCalculations[shipToState].Calculate();
}
}
public interface IShippingCalculation
{
State State { get; }
decimal Calculate();
}
public class AlaskShippingCalculation : IShippingCalculation
{
public State State { get { return State.Alaska; } }
public decimal Calculate()
{
return 15m;
}
}
public class NewYorkShippingCalculation : IShippingCalculation
{
public State State { get { return State.NewYork; } }
public decimal Calculate()
{
return 10m;
}
}
public class FloridaShippingCalculation : IShippingCalculation
{
public State State { get { return State.Florida; } }
public decimal Calculate()
{
return 3m;
}
}
浙公网安备 33010602011771号