重构第11天 使用策略代替Switch(Switch to Strategy)

时间:2021-08-31 17:38:10

理解:策略就是平常设计模式中所说的策略模式。因为当你有一个庞大的switch方法的时候,每一次新加一个条件,都要去修改这个方法,这样耦合性太高,不易维护也不易扩展。这样我们就可以使用策略的设计模式,使得每一种情况都封装在自己的类中,来提高扩展性和降低耦合性。

详解

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace _31DaysRefactor
{ public class ClientCode
{ public decimal CalculateShipping()
{
ShippingInfo shippinginfo = new ShippingInfo(); return shippinginfo.CalclateShippingAmount(State.Alaska);
} } public enum State
{
Alaska,
NewYork,
Florida
} public class ShippingInfo
{ public decimal CalclateShippingAmount(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;
}
}
}

为了完成switch重构,我们需要把每一种条件封装成一个独立的类,然后这些类提取出一个公共接口,每个类都实现该接口。下次如果你想添加新的条件,只需要新增一个实现该公共接口的类即可。

这里我们提取出一个公共接口IShippingCalculation,这个类包含一个方法decimal Caculate()和一个属性 State State { get; }。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace _31DaysRefactor
{ public class ClientCode
{ public decimal CalculateShipping()
{
IShippingInfo shippingInfo = new ShippingInfo();
return shippingInfo.CalculateShippingAmount(State.Alaska);
} } public enum State
{
Alaska,
NewYork,
Florida
} public interface IShippingCalculation
{
decimal Caculate();
} public interface IShippingInfo
{
decimal CalculateShippingAmount(State state);
} public class ShippingInfo : IShippingInfo
{
private IDictionary<State, IShippingCalculation> ShippingCalculations { get; set; } public ShippingInfo()
{
ShippingCalculations = new Dictionary<State, IShippingCalculation>(){
{State.Alaska,new AlaskShippingCaculation()},
{State.Florida,new FloridaShippingCaculation()},
{State.NewYork,new NewYorkShippingCaculation()}
};
} public decimal CalculateShippingAmount(State shipToState)
{
return this.ShippingCalculations[shipToState].Caculate();
} } public class AlaskShippingCaculation : IShippingCalculation
{
public State State { get { return State.Alaska; } } public decimal Caculate()
{
return 15m;
}
} public class NewYorkShippingCaculation : IShippingCalculation
{
public State State { get { return State.NewYork; } } public decimal Caculate()
{
return 10m;
}
} public class FloridaShippingCaculation : IShippingCalculation
{
public State State { get { return State.Florida; } } public decimal Caculate()
{
return 3m;
}
}
}