zoukankan      html  css  js  c++  java
  • 重构11-Switch to Strategy(Switch到策略模式)

    重构没有固定的形式,多年来我使用过不同的版本,并且我敢打赌不同的人也会有不同的版本。 该重构适用于这样的场景:switch语句块很大,并且会随时引入新的判断条件。这时,最好使用策略模式将每个条件封装到单独的类中。实现策略模式的方式是很多的。我在这里介绍的策略重构使用的是字典策略,这么做的好处是调用者不必修改原来的代码。

    public class ClientCode {
    public double CalculateShipping() {
    ShippingInfo shippingInfo = new ShippingInfo();
    return shippingInfo.CalculateShippingAmount(State.Alaska);
    }
    }
    public enum State {
    Alaska, NewYork, Florida
    }
    public class ShippingInfo {
    public double CalculateShippingAmount(State shipToState) {
    switch (shipToState) {
    case State.Alaska:
    return GetAlaskaShippingAmount();
    case State.NewYork:
    return GetNewYorkShippingAmount();
    case State.Florida:
    return GetFloridaShippingAmount();
    default:
    return 0d;
    }
    }

    private double GetAlaskaShippingAmount() {
    return 15d;
    }
    private double GetNewYorkShippingAmount() {
    return 10d;
    }
    private double GetFloridaShippingAmount() {
    return 3d;
    }
    }
    要应用该重构,需将每个测试条件至于单独的类中,这些类实现了一个共同的接口。然后将枚举作为字典的键,这样就可以获取正确的实现,并执行其代码了。以后如果希望添加新的条件,只需添加新的实现类,并将其添加至ShippingCalculations字典中。正如前面说过的,这不是实现策略模式的唯一方式。我在这里将字体加粗显示,是因为肯定会有人在评论里指出这点:)用你觉得好用的方法。我用这种方式实现重构的好处是,不用修改客户端代码。所有的修改都在ShippingInfo类内部。 
    Jayme Davis指出这种重构由于仍然需要在构造函数中进行绑定,所以只不过是增加了一些类而已,但如果绑定IShippingCalculation的策略可以置于IoC中,带来的好处还是很多的,它可以使你更灵活地捆绑策略
    public class ClientTest {
    public Double CalculateShipping() {
    ShippingInfo shippingInfo = new ShippingInfo();
    return shippingInfo.CalculateShippingAmount(State.Alaska);
    }
    }
    public enum State {
    Alaska, NewYork, Florida
    }
    public class ShippingInfo {
    private Dictionary<State, IShippingCalculation> ShippingCalculations;

    public ShippingInfo() {
    ShippingCalculations =new Hashtable<State, IShippingCalculation>();
    ShippingCalculations.put(State.Alaska, new AlaskShippingCalculation());
    ShippingCalculations.put(State.NewYork, new NewYorkShippingCalculation());
    ShippingCalculations.put(State.Florida, new FloridaShippingCalculation());
    }

    public Double CalculateShippingAmount(State shipToState) {
    return ShippingCalculations.get(shipToState).Calculate();
    }
    }
    public interface IShippingCalculation {
    Double Calculate();
    }
    public class AlaskShippingCalculation implements IShippingCalculation {
    public Double Calculate () {
    return 15d;
    }
    }
    public class NewYorkShippingCalculation implements IShippingCalculation {
    public Double Calculate () {
    return 10d;
    }
    }
    public class FloridaShippingCalculation implements IShippingCalculation {
    public Double Calculate () {
    return 3d;
    }
    }
    为了使这个示例圆满,我们来看看在ShippingInfo构造函数中使用Ninject为IoC容器时如何进行绑定。需要更改的地方很多,主要是将state的枚举放在策略内部,以及Ninject向构造函数传递一个IShippingInfo的IEnumerable泛型。接下来我们使用策略类中的state属性创建字典,其余部分保持不变。(感谢Nate Kohari和Jayme Davis)
    public interface IShippingInfo {
    Double CalculateShippingAmount(State state);
    }

    public class ClientCode {
    public IShippingInfo ShippingInfo;
    public Double CalculateShipping() {
    return ShippingInfo.CalculateShippingAmount(State.Alaska);
    }
    }
    public enum State{
    Alaska, NewYork, Florida;
    }

    public class ShippingInfo implements IShippingInfo{
    private Dictionary<State, IShippingCalculation> ShippingCalculations=new Hashtable<State, IShippingCalculation>();
    public ShippingInfo(IShippingCalculation<State> shippingCalculations) {
    for(State state:State.values()) {
    ShippingCalculations.put(state, shippingCalculations);
    }
    }
    public Double CalculateShippingAmount(State shipToState) {
    return ShippingCalculations.get(shipToState).Calculate();
    }
    }

    public interface IShippingCalculation<State> {
    State getState();
    Double Calculate();
    }

    public class AlaskShippingCalculation implements IShippingCalculation {
    @Override
    public State getState() {
    return State.Alaska;
    }
    @Override
    public Double Calculate() {
    return 15d;
    }
    }

    public class NewYorkShippingCalculation implements IShippingCalculation {
    @Override
    public State getState() {
    return State.NewYork;
    }
    @Override
    public Double Calculate() {
    return 10d;
    }
    }

    public class FloridaShippingCalculation implements IShippingCalculation {
    @Override
    public State getState() {
    return State.Florida;
    }
    @Override
    public Double Calculate() {
    return 3d;
    }
    }
     
     
     





  • 相关阅读:
    谷歌翻译python接口
    SRILM的安装方法
    语言模型srilm基本用法
    SRILM语言模型格式解读
    矩阵理解
    python生成器 协程
    python Queue模块使用
    scrapy 学习笔记2
    scrapy 学习笔记1
    xpath语法规则
  • 原文地址:https://www.cnblogs.com/jgig11/p/5786325.html
Copyright © 2011-2022 走看看