1

我有一个接口——虽然它也可以是一个抽象类——它应该允许它的实现者指定他们是否支持特定的特性,我正在寻找实现这一点的最佳方法。

这里有几种选择:

查看 BCL,我看到该类具有和 之类Stream的属性,可用于检查是否支持某个功能,如果我执行不支持的操作,则抛出一个 。CanReadCanSeekNotSupportedException

public interface IHandler
{
    bool SupportsA { get; }
    bool SupportsB { get; }

    void A();
    void B();
}

这对我来说是一种合适的方法,尽管我有很多可能受支持或不支持的功能,而且我不想为每个功能定义一个“SupportsX”属性。

我也非常喜欢按位Enum值,我认为另一种方式是:

[Flags]
public enum HandlerFeature
{
    None = 0
    A = 1,
    B = 2,
    C = 4
}

public interface IHandler
{
    HandlerFeature Features { get; }

    void A();
    void B();
    void C();
}

并且可以编写这样的扩展方法:
bool Supports<T>(this T handler, HandlerFeature feature) where T : IHandler

我认为这也比其他方法更漂亮,但我不禁认为,如果每个Enum值都对应合同中的一个成员,我应该能够更明确地标记这些成员。然后我想到了属性:

public interface IHandler
{
    [HandlerRequires(Feature.None)]
    HandlerFeature Features { get; }

    [HandlerRequires(Feature.A)]
    void A();

    [HandlerRequires(Feature.B)]
    void B();

    [HandlerRequires(Feature.A | Feature.B)]
    void AB();

    [HandlerRequires(Feature.C)]
    void C();
}

虽然我不知道如何在运行时利用这样的属性,但它确实使接口定义看起来足够明确

这有最佳实践吗?
还是您推荐的其他方法?
还是我指定的有什么问题?

4

1 回答 1

1

如果您必须构建一个必须使用所有这些东西的接口,我建议您使用布尔值来完成,因为开发人员在实现该接口时必须为该属性指定一个值。使用标记的枚举或属性可能会导致类中没有实现方法 A,但开发人员只是忘记正确设置属性或枚举。在这种情况下,编译器不会发出错误。

无论如何,我建议您不要构建这样的“胖”界面。我鼓励你阅读“接口隔离原则”,它是面向对象设计的 SOLID 原则的一部分(谷歌它,你会找到几篇文章)。它指出不应强迫客户依赖他们不使用的方法。这样做的结果是您使用多个小接口而不是一个包含多个方面的接口。现在我不知道您的工作环境,但如果您的界面集成了几个横切关注点,例如除了其基本业务功能之外的日志记录,我强烈建议放弃接口的日志记录并改用装饰器模式(另外,如果您不知道,请在 Google 上搜索 :-) )。

希望这可以帮助。

于 2013-04-26T16:41:08.293 回答