我有一个课程有两个重要的功能:
public class Foo {
//plenty of properties here
void DoSomeThing(){/*code to calculate results*/}
void SaveSomething(){/* code to save the results in DB*/}
}
Run Code Online (Sandbox Code Playgroud)
SaveSomething()使用计算结果 DoSomeThing().
问题是我们不能在SaveSomething()之前打电话DoSomeThing()或如果发生这种情况,结果不是真实的结果.我的意思是调用顺序很重要,这是维护代码的一个问题.(当新的一个被添加到团队中时).
有没有办法管理这个?
我想到如下3种方法
SaveSomething()如果它之前调用过,则抛出异常DoSomeThing()具有bool被设置在DoSomeThing()和SaveSomething()代码改变为:
bool resultsAreCalculated = false;
void SaveSomething(){
if (!resultsAreCalculated) {
DoSomeThing();
// the resultsAreCalculated = true; is set in DoSomeThing();
// can we throw some exception?
}
/* code to save the results in DB*/
}
Run Code Online (Sandbox Code Playgroud)实现它流畅如:
Foo x = new Foo();
x.DoSomeThing().SaveSomething();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,重要的是要保证不会发生这种情况:
x.SaveSomething().DoSomeThing();
Run Code Online (Sandbox Code Playgroud)现在,我使用第二种方法.有没有更好的方法还是足够的?
小智 13
理想情况下,需要遵循执行中的某个顺序的方法表示或暗示需要实现某种类型的工作流.
有一些设计模式支持强制执行类似工作流的线性执行顺序,例如模板方法模式或策略.
采取模板方法途径,你的Foo类将有一个定义执行顺序的抽象基Do()和Save()喜欢的东西:
public abstract class FooBase
{
protected abstract void DoSomeThing();
protected abstract void SaveSomething();
public void DoAndSave()
{
//Enforce Execution order
DoSomeThing();
SaveSomething();
}
}
public class Foo : FooBase
{
protected override void DoSomeThing()
{
/*code to calculate results*/
}
protected override void SaveSomething()
{
/* code to save the results in DB*/
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您的类消费者只能访问,DoAndSave()并且不会影响您的预期执行顺序.
还有另一种模式可以处理工作流/状态转换类型的情况.您可以参考命令链和状态模式.
响应您的评论:这遵循相同的模板构思,您在模板中添加了另一个步骤,想象您想在保存之前验证结果,您可以将模板扩展为:
public abstract class FooBase
{
protected abstract void DoSomeThing();
protected abstract void SaveSomething();
protected abstract bool AreValidResults();
public void DoAndSave()
{
//Enforce Execution order
DoSomeThing();
if (AreValidResults())
SaveSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
当然,对于更精细的工作流程,我在最初答案的最后提到了状态模式,您可以更精细地控制从一个状态到另一个状态的转换条件.
帮助避免用户错误的一个选项是通过传递变量来明确它.通过这样做,它为用户提出了一个标志,他们需要在调用SaveSomething(...)之前获得结果(即DoSomething()).
results = DoSomething(); // returns the results to be saved
SaveSomething(results);
Run Code Online (Sandbox Code Playgroud)