当其中一个实现需要额外的步骤时,C#模式用于避免泄漏抽象

Jam*_*son 5 .net c# design-patterns leaky-abstraction

我正在实现一个ITracker看起来像这样的接口:

public interface ITracker
{
    void Track(ITrackerEvent trackerEvent);
}
Run Code Online (Sandbox Code Playgroud)

我最初创建了这个包装Mixpanel.NET的接口的实现.然后我创建了另一个包装Application Insights的程序.但是,Application Insights需要Flush()将数据发送到服务器.

我不想仅仅因为其中一个实现需要一个方法而污染ITracker接口Flush().它会感觉像是一个漏洞的抽象.

但是,我需要在某个时候调用此方法(可能在应用程序关闭时)并且不希望每次Track调用时都这样做.

当Tracker在会话结束时被垃圾收集时,是否可以调用方法?这甚至是一个好方法吗?

我觉得我在这里错过了一招!

Ler*_*eri 5

我会ITracker使用事务相似的模式,因为可能存在您可能想要丢弃跟踪器事件,回滚或修改它们的情况:

public interface ITracker
{
    void Track(ITrackerEvent trackerEvent);

    void Commit();
}
Run Code Online (Sandbox Code Playgroud)

然后按照实现:

  • 我打算Flush在内部Commit寻求应用程序见解.
  • 我在内部集合中编写跟踪器事件(List<ITrackerEvent>或者BlockingCollection<ITrackerEvent>如果涉及并发)Track,然后使用当前逻辑Mixpanel.NETCommit方法实现中调用api Mixpanel.NET.

建议: ITracker还应该实施,IDisposable因为跟踪器通常使用需要处理的资源.

  • 显然,在这种情况下,“ IDisposable”将使合同清晰明了。 (2认同)

pli*_*nth 5

在Leri的基础上,我会更多地考虑跟踪器可能需要做的事情.

我倾向于做这样的事情:

public interface ITracker {
    void BeginTracking();
    void Track(ITrackerEvent trackerEvent);
    void EndTracking();
}
Run Code Online (Sandbox Code Playgroud)

然后所有跟踪器都会了解它们何时开始以及何时完成.这很重要,因为跟踪器可能持有的资源不应超过必要的时间.如果跟踪器不需要使用任何一个BeginTracking或者EndTracking,则实现是微不足道的.一个简单的实现不是漏洞的抽象.漏洞抽象是一种不适用于所有实现的抽象.

现在假设你完全没有在每个跟踪器中有两个额外的方法(为什么?).您可以改为使用带外的ITrackerEvents并涵盖Begin和End的语义含义.我不喜欢这个.它要求每个跟踪器都有特殊的代码来处理带外事件.

您还可以拥有一个单独的界面

public interface IDemarcatedTracker : ITracker {
    void BeginTracking();
    void EndTracking();
}
Run Code Online (Sandbox Code Playgroud)

这要求您在调用代码中包含特殊案例代码,以检查ITracker是否也是IDemarcatedTracker:

public void BeginTracking(ITracker tracker)
{
    IDemarcatedTracker demarcatedTracker = tracker as IDemarcatedTracker;
    if (demarcatedTracker != null)
        demarcatedTracker.BeginTracking();
}
Run Code Online (Sandbox Code Playgroud)

而不是过度夸大事物,但我也想知道当跟踪器失败时会发生什么?只是盲目地抛出异常?而这里的抽象实际上是漏洞.跟踪器没有让您知道它无法跟踪的过程.

在您的情况下,您可能希望返回布尔值(有限信息),错误代码(更多信息)或错误类/结构.或者您可能希望获得抛出的标准异常.或者您可能希望Begin()方法包含在跟踪中发生错误时调用的委托.