假设我有各种各样的代码段要运行,但在每个部分之前,我必须运行Start()
方法,然后在每个部分之后我需要运行Complete()
方法。但是,如果代码部分中抛出异常,我想运行Fail(string message)
方法而不是Complete()
。是否有优雅的设计模式,使其整洁,易于重复?
例如,假设我有一个名为Thing
的类型,它包含一个Start()
方法,该方法向记录数据库表添加一行以反映任务正在进行中,{{1}更改该行以反映任务完成的方法以及更改行以反映任务失败的Complete()
方法。这些只是一些例子,他们可以做任何设置和整理类型的任务。
天真的实现可能只是手动调用这些方法:
Fail(string message)
但如果我要在很多不同的地方重复这个问题,最终会造成很多重复,很容易忘记调用public void DoStuff()
{
var thing = new Thing();
thing.Start();
try
{
DoImportantStuff();
thing.Complete();
}
catch (Exception e)
{
thing.Fail(e.Message);
}
}
或者把它搞砸了微妙的方式。
在C#中,有Complete
模式,它提供了封装大部分内容的好方法。例如,如果我的using
类型如下所示:
Thing
我的public class Thing : IDisposable
{
public Thing(){
Start();
}
private void Start() { /* start */ }
private void Complete() { /* complete */ }
public void Dispose()
{
Complete();
}
}
方法现在可以简化为:
DoStuff()
哪个更好。但是如果抛出异常,它不允许我调用public void DoStuff()
{
using(new Thing())
{
DoImportantStuff();
}
}
而不是Fail
,因为(我认为!)Complete
方法基本上是在Dispose
块中调用的
我想过在Finally
块中有一个try/catch
,然后在using
块内设置一个thing.HasFailed
标志,然后在catch
中使用它}方法来决定是Dispose
还是Complete
。但这似乎有点繁琐,我希望Fail
的消费者尽可能少地做,以使其正常工作。
那么是否有一个设计模式封装了我想要做的事情,并且每次都不需要手动编写Thing
?
答案 0 :(得分:5)
你可以这样Thing
:
public class Thing
{
private void Start() { /* start */ }
private void Complete() { /* complete */ }
private void Fail(string message) {}
public void DoAction(Action action)
{
this.Start();
try
{
action();
this.Complete();
}
catch (Exception e)
{
this.Fail(e.Message);
}
}
}
并像这样使用它:
Thing thing = new Thing();
thing.DoAction(this.DoStuff);
答案 1 :(得分:1)
该模式称为“模板方法”。您可以在“面向方面编程”标题下找到您的实现。 (https://msdn.microsoft.com/en-us/library/aa288717(v=vs.71).aspx)
答案 2 :(得分:0)
使用Delegates。
public class Thing : IDisposable
{
private void Start() { /* start */ }
private void Complete() { /* complete */ }
private void Fail(string _szMessage) {/* fail */}
public delegate void ProcessClientStuff();
private ProcessClientStuff m_delegateClientStuff;
public Thing(ProcessClientStuff _delegateClientStuff) {m_delegateClientStuff = _delegateClientStuff}
public void Dostuff()
{
Start();
try
{
m_delegateClientStuff();
Complete();
}
catch(Exception e)
{
Fail(e.Message);
}
}
}
void ClientStuff()
{
Console.WriteLine("Hello");
}
Thing oClientStuffProcessor = new Thing(ClientStuff);
oClientStuffProcessor.Dostuff();