推荐一种设计模式

时间:2011-08-08 02:55:28

标签: c# design-patterns solid-principles

我正在处理工作项目的应用程序。根据工作项的状态,可以使用许多操作。 “完成”“取消”“重新分配”等......

为我提供动作的功能,我现在有一个看起来像这样的界面......

public interface IActionProvider{
    public void Complete(WorkItem workItem);
    public void Cancel (WorkItem workItem);
    public void Reassign(WorkItem workItem);
}

然后根据工作项的其他细节,我有接口的具体实现。仅举例......

public class NormalActionProvider :IActionProvider
{
    ...
}

public class UrgentActionProvider : IActionProvider
{
   ....
}

问题是,如果我想添加一个新动作,说......“委托”我必须更新界面,当然这对所有实现都有影响。

这是否违反了开放/关闭原则?你能推荐一个可以帮助我的设计模式或重构吗?

5 个答案:

答案 0 :(得分:11)

看起来命令模式是合适的。您可以修改/添加更多命令。命令类与主程序分离。

public interface IActionProvider{
    public void execute(WorkItem item,ActionType actionType);
}

ActionType表示完成,取消&等等。您可以继续添加更多操作类型&插件适当的命令类。

答案 1 :(得分:3)

您总是可以将一个Decorator添加到IActionProvider界面(按照Decorator design pattern)。

答案 2 :(得分:0)

这取决于您使用IActionProvider尝试实现的目标。如果您真的想要使每个实现必须能够执行您认为重要的所有操作,那么它应该是它们实现的接口的一部分。如果提前做好计划,接口工作效果最好,这样他们就不必持续改变。

但听起来您并不一定希望所有提供商都能实施所有操作。我需要知道更多细节才能提供好的建议,但是一个例子是让提供者针对一种事件Bus初始化自己。他们可以订阅他们关心的事件,并仅针对特定实现有意义的事件执行操作。

答案 3 :(得分:0)

“取决于工作项的状态”,带来状态设计模式

不管怎样,你必须重构界面并最终破坏客户合同。

如果我已正确理解您的问题,那么您有一个WorkItemProcessor,其状态会发生变化 在发送给它的WorkItem上。

因此,您的WorkItemProcessor变为

// Context
    public class WorkItemProcessor
    {
        public IState CurrentState { get; set; }

        public WorkItemProcessor(IState initialState)
        {
            CurrentState = initialState;
        }

        public void Process(WorkItem workItem)
        {
            CurrentState.Handle(this, workItem);
        }
    }

然后我们定义WorkItemProcessor可能存在的多个状态

// State Contract
    public interface IState
    {
        void Handle(WorkItemProcessor processor, WorkItem item);
    }

    // State One
    public class CompleteState : IState
    {
        public void Handle(WorkItemProcessor processor, WorkItem item)
        {
            processor.CurrentState = item.CompletenessConditionHoldsTrue ? (IState) this : new CancelState();
        }
    }

    // State Two
    public class CancelState : IState
    {
        public void Handle(WorkItemProcessor processor, WorkItem item)
        {
            processor.CurrentState = item.CancelConditionHoldsTrue ? (IState) this : new CompleteState();
        }
    }

假设您的WorkItem看起来像

 // Request
    public class WorkItem
    {
         public bool CompletenessConditionHoldsTrue { get; set; }

         public bool CancelConditionHoldsTrue { get; set; }
    }

把它们放在一起

static void Main()
    {
      // Setup context in a state 
      WorkItemProcessor processor = new WorkItemProcessor(new CancelState());

      var workItem1 = new WorkItem {  CompletenessConditionHoldsTrue = true };
      var workItem2 = new WorkItem {  CancelConditionHoldsTrue = true };

      // Issue requests, which toggles state 
      processor.Process(workItem1);
      processor.Process(workItem2);

      Console.Read();
    }

希望这能让你更接近。欢呼声。

答案 4 :(得分:0)

我也会选择命令模式。作为增强,您可以将它与抽象工厂方法结合使用,这样您就可以为每个命令类创建一个工厂类,并且所有这些工厂都实现了一个公共工厂接口。

例如:

// C#
public interface ICommand { void Execute(); }

public interface ICommandFactory { ICommand Create(); }

public class CommandFactoryManager
{
    private IDictionary<string, ICommandFactory> factories;

    public CommandFactoryManager()
    {
        factories = new Dictionary<string, ICommandFactory>();
    }

    public void RegisterCommandFactory(string name, ICommandFactory factory)
    {
        factories[name] = factory;
    }

    // ...
}

这样,您可以动态注册新的命令工厂。例如,您可以在运行时加载DLL并使用反射获取实现ICommandFactory接口的所有类,并且您有一个简单的插件系统。