假设我有各种各样的代码段要运行,但在每个部分之前,我必须运行一个Start()
方法,然后在每个部分后我需要运行一个Complete()
方法.但是,如果在代码部分抛出异常,我想运行一个Fail(string message)
方法而不是Complete()
.是否有一种优雅的封装设计模式,使其整洁,易于重复?
例如,假设我有一个名为的类型Thing
,其中包含一个Start()
方法,该方法将一行添加到日志记录db表以反映任务正在进行中,该Complete()
方法更改该行以反映任务已完成以及Fail(string message)
更改方法的方法行反映任务失败.这些只是一些例子,他们可以做任何设置和整理类型的任务.
天真的实现可能只是手动调用这些方法:
public void DoStuff() { var thing = new Thing(); thing.Start(); try { DoImportantStuff(); thing.Complete(); } catch (Exception e) { thing.Fail(e.Message); } }
但是如果我不得不在很多不同的地方重复这一点,它最终会造成很多重复,并且可能很容易忘记以Complete
某种微妙的方式打电话或弄乱它.
在C#中,有这种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
必须尽可能少地使其正常工作.
那么是否有一个设计模式封装了我想要做的事情并避免了try\catch
每次手动编写的需要?
你可以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);