重构帮助 - 策略模式

时间:2009-07-21 15:56:37

标签: design-patterns refactoring strategy-pattern

此处的对象是更新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

3 个答案:

答案 0 :(得分:3)

首先,如果您要将策略模式与接口一起使用,您可能需要这样的接口。

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();

答案 1 :(得分:3)

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

答案 2 :(得分:0)

我认为你要找的是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...
    }
}