我正在处理工作项目的应用程序。根据工作项的状态,可以使用许多操作。 “完成”“取消”“重新分配”等......
为我提供动作的功能,我现在有一个看起来像这样的界面......
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
{
....
}
问题是,如果我想添加一个新动作,说......“委托”我必须更新界面,当然这对所有实现都有影响。
这是否违反了开放/关闭原则?你能推荐一个可以帮助我的设计模式或重构吗?
答案 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接口的所有类,并且您有一个简单的插件系统。