【问题标题】:refactor help - strategy pattern重构帮助 - 策略模式
【发布时间】:2009-07-21 15:56:36
【问题描述】:

这里的对象是更新 UI。我通常在客户端上执行此操作,但是此应用程序使用后面的代码。无论如何,我的问题是我正在尝试清理这些 if else 语句,并且我认为策略模式可能是合适的。我不需要为我完成所有工作,但如果你能给我一些指示,让我继续前进。我是否先创建一个接口,然后每个策略都实现该接口?泛型在这里有用吗?接口中应该有哪些类型的方法?任何能让我前进的事情都会非常感激。

if (someObject.Status == 'A') {
                    btnRecordCall.Enabled = false;
                    btnAddMailOrStatusAction.Enabled = false;
                    btnPayments.Enabled = false;
                    btnAddressMaint.Enabled = false;
                    btnFilter.Enabled = false;
                    btnAddCoverage.Enabled = false;
                    btnPolicyForms.Enabled = false;
                    lblIsArchived.Text = "********** THIS CLAIM HAS BEEN ARCHIVED **********";
                } else if (someObject.Status == 'D') {
                    btnRecordCall.Enabled = false;
                    btnAddMailOrStatusAction.Enabled = false;
                    btnPayments.Enabled = false;
                    btnAddressMaint.Enabled = false;
                    btnFilter.Enabled = false;
                    btnAddCoverage.Enabled = false;
                    btnPolicyForms.Enabled = false;
                    lblIsArchived.Text = "- De-archive Request Pending";
                } else {
                    btnRecordCall.Enabled = true;
                    btnAddMailOrStatusAction.Enabled = true;
                    btnPayments.Enabled = true;
                    btnAddressMaint.Enabled = true;
                    btnFilter.Enabled = true;
                    btnAddCoverage.Enabled = true;
                    btnPolicyForms.Enabled = true;
                    lblIsArchived.Text = "";
                }

谢谢, ~ck

【问题讨论】:

    标签: design-patterns refactoring strategy-pattern


    【解决方案1】:

    如果无论状态如何,所有按钮都获得相同的启用,如您的示例中那样,那么我会将其隐藏在按钮列表中并对其进行迭代。然后你的策略参数归结为一个布尔值和一个字符串——无论如何都很容易做到这一点。如果它有更大的复杂性,那么实现设置控件的接口的不同类将是有序的,可能有一个包含整体逻辑的抽象超类。

    【讨论】:

      【解决方案2】:

      首先,如果您要使用带有接口的策略模式,您可能需要这样的接口。

      public interface IStrategyUI
      {
         void Execute();
      }
      

      然后是你的逻辑的几个类

      public class StatusAStrategy : IStrategyUI
      {
        public void Execute()
         {
            //implement
         }
      }
      

      那么你的 if 语句在技术上可以是一个工厂。

      IStrategyUI logic;
      
      switch(someObject.Status)
      {
          case 'A':   logic = new StatusAStrategy();
                  //etc etc
      
      }
      
      logic.Execute();
      

      或者您可以将此对象作为接口返回,并将 switch 语句封装在另一个方法或工厂类中。

      这样你就可以这样使用了。

      IStrategyUI logic = StrategyFactory.GetStrategy(status);
      logic.Execute();
      

      这取决于你。

      另外,我在这里没有使用收容类,但如果你愿意,可以使用。

      您也可以对委托执行此操作。

      收容等级

       class StrategyHolder
          {
              public Action Strategy { get; set; }
      
              public void Execute()
              {
                  if(this.Strategy != null)
                       this.Strategy();
              }
          }
      

      不同的策略方法。

      void EnableStatusA()
      {
         //do everything for status A
      }
      

      切换语句

      StrategyHolder logic = new StrategyHolder();
      
      switch(someObject.Status)
          {
              case 'A':   logic.Strategy = EnableStatusA;
                      //etc etc
      
          }
      
      return logic;
      

      从外面调用它。

      StrategyHolder logic = StrategyFactory.GetStrategy(status);
      logic.Execute();
      

      【讨论】:

      • 谢谢斯坦。在实现中的执行方法中,如何获取对页面控件的引用?我是否将引用传递给页面并执行 findcontrol('someId')?还是有更好的方法?
      • 是的,您可以传递对页面本身的引用,然后执行与之前相同的操作,即 page.lblIsArchived.Text = "";等等。您可以在构造函数或 Execute 方法中传递对 Page 的引用。由你决定。
      【解决方案3】:

      我认为您正在寻找的是State 模式。这类似于策略模式,只是每个状态对象在创建时通常都会被赋予对上下文对象(在您的情况下是表单)的引用。这允许不同的状态对上下文对象做一些事情以响应事件。

      在实现状态模式时,通常最好让每个单独的状态都从抽象基类继承。然后,基类可以在虚拟方法中实现默认操作,然后您只需覆盖每个状态不同的操作。

      public interface IFormState
      {
          void EnableDisableControls();
      }
      
      public class DefaultState : IFormState
      {
          private MyForm context;
      
          public DefaultState(MyForm context)
          {
              this.context = context;
          }
      
          protected MyForm Context
          {
              get
              {
                  return this.context;
              }
          }
      
          public virtual void EnableDisableControls()
          {
              this.context.btnRecordCall.Enabled = true;
              this.context.btnAddMailOrStatusAction.Enabled = true;
              this.context.btnPayments.Enabled = true;
              this.context.btnAddressMaint.Enabled = true;
              this.context.btnFilter.Enabled = true;
              this.context.btnAddCoverage.Enabled = true;
              this.context.btnPolicyForms.Enabled = true;
              this.context.lblIsArchived.Text = "";
          }
      }
      
      public class StateA : DefaultState
      {
          public StateA(MyForm context)
              : base(context)
          {
          }
      
          public override void EnableDisableControls()
          {
              base.EnableDisableControls();
      
              this.Context.lblIsArchived.Text = "********** THIS CLAIM HAS BEEN ARCHIVED **********";
              // etc...
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-11
        • 1970-01-01
        • 2011-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多