通过添加新接口而不是扩展现有接口来添加功能

时间:2009-11-19 15:05:42

标签: c# .net interface

我需要为现有界面添加一些新功能。项目中已经有很多类实现它,但其中一些不需要新的功能集。我的第一种方法是将新功能添加到现有接口并在任何地方实现,在适用的地方添加无操作功能等。但现在我想知道是否有更好的方法来做到这一点。

举个例子:

// Everything able to produce a waveform must implement this interface.
interface IWaveformResource
{
    int Collect( Stream _target, int _sampleCount );
}

// A waveform stored in a file
class FileWaveform : IWaveformResource
{
    public int Collect( Stream _target, int _sampleCount )
    {
        // ...
    }
}

// A sine waveform.
class SineWaveform : IWaveformResource
{
    public int Collect( Stream _target, int _sampleCount )
    {
        // ...
    }
}

// Added feature, we want to be able to specify the read position
interface IWaveformResource
{
    int Collect( Stream _target, int _sampleCount );
    int ReadOffset { get; set; }
}

class FileWaveform : IWaveformResource
{
    public int Collect( Stream _target, int _sampleCount )
    {
        // ...
    }

    // Moves the associated file pointer accordingly.
    int ReadOffset { get; set; }
}

class SineWaveform : IWaveformResource
{
    public int Collect( Stream _target, int _sampleCount )
    {
        // ...
    }

    // There's no point in setting or retrieving a sine wave's read position.
    int ReadOffset { get; set; }
}

另一种选择是创建一个新的接口,该接口只能通过可定位的波形流来实现,例如。 FileWaveform:

interface IPositionableWaveform
{
    int ReadOffset { get; set; }
}

// A waveform stored in a file
class FileWaveform : IWaveformResource, IPositionableWaveform
{
    public int Collect( Stream _target, int _sampleCount )
    {
        // ...
    }
}

并像这样使用它:

private List<IWaveformResource> mResources;
public int ReadOffset
{
    set
    {
        foreach( IWaveformResource resource in mResources )
        {
            if( resource is IPositionableWaveform )
            {
                ((IPositionableWaveform)resource).ReadOffset = value;
            }
        }
    }
}

请注意,在这种方法中,我并没有强制IPositionableWaveform也是IWaveformResource。

我想知道是否有比这更优雅的解决方案,提前谢谢。

2 个答案:

答案 0 :(得分:8)

没有。不幸的是,改变现有界面是一个重大改变。

顺便说一下,这是支持抽象类接口的一个更强大的参数 - 使用抽象基类,你可以在不破坏API的情况下添加成员(使用默认实现)。

介绍第二个接口(继承自第一个接口)可能是您的最佳选择。根据你所描述的,我所做的主要改变是:

public interface IWaveformResource : IAudioResource { ... }

这样,波形资源显然也是一种音频资源。

答案 1 :(得分:3)

如果并非所有实现该接口的类都需要新功能,那么它很可能永远不会属于该接口。