3

在我当前的项目中,我有一个相当时髦的设备,它可以执行各种流式传输选项,例如视频流式传输、音频流式传输和某些类型的数据流式传输。

每个设备仅支持有限数量的这些流中的每一个。为了论证起见,假设它可以支持 2 个视频流和 1 个音频流。

我设计的有点像下面。(大多数应用程序逻辑都被忽略了。)

public class FunkyDevice
{
    int openVideoStreams;
    int openAudioStreams;

    public VideoStream openVideoStream(int id)
    {
        if (openVideoStreams < 2)
        {
            openVideoStreams++;
            return new VideoStream(...);
        }
    }
    public AudioStream openAudioStream(int id)
    {
        if (openAudioStreams < 1) 
        {
            openAudioStreams++;
            return new AudioStream(...);            
        }
    }
}

但是,现在我需要支持超过 1 个设备。我将这些分组在一个用户会话中。每个用户会话也限制了每个流的数量,但是这些数字当然与设备限制不同(否则问题就太容易了)。例如,我可以有 3 个视频流(到 1、2 或 3 个不同的设备)和仍然 1 个音频流。

我处理这个问题的最佳尝试如下:

public class UserSession
{
    int openVideoStreams;
    int openAudioStreams;

    public VideoStream openVideoStream(int deviceId, int id)
    {
        if (openVideoStreams < 3)
        {
            openVideoStreams++;
            return getDevice(deviceId).openVideoStream(id);
        }
    }
    public AudioStream openAudioStream(int deviceId, int id)
    {
        if (openAudioStreams < 1) 
        {
            openAudioStreams++;
            return getDevice(deviceId).openAudioStream(id);     
        }
    }
}

如您所见, 和 的公共接口FunkyDevice几乎UserSession相同,只是其中的每个方法UserSession都有一个附加参数deviceId。在我的实际应用程序中,我有超过 2 种不同类型的流(并且还希望执行其他操作,例如关闭流),因此接口变得非常大。

在不引入此代码重复的情况下,是否有更好的模式来促进这一点?

4

2 回答 2

4

您可以根据标识符类创建一个通用的接口:

public interface IStreamManager<TIdentifier>{

 VideoStream openVideoStream(TIdentifier id);
 AudioStream openAudioStream(TIdentifier id);

}

,首先你会在哪里:

public class FunkyDeviceStreamIdentifier {
   public int id;
}

而对于第二个你有:

public class UserDeviceStreamIdentifier {
   public int deviceId;
   public int id;
}

(您可能希望将它们struct改为 s,和/或引入工厂方法或隐式转换,使它们更易于处理)

于 2013-08-08T10:05:00.700 回答
1

我一直在考虑一个解决方案,也许有一个可以让生活更轻松的解决方案。

你可以StreamingSettings上课:

public class StreamingSettings
{
    public int StreamId { get; set; }
}

您还可以设计一个继承的用户会话流设置类StreamingSettings

public class UserSessionStreamingSettings : StreamingSettings
{
    public int DeviceId { get; set; }
}

现在,您可以按如下方式使用泛型:

    // Check that the generic constraint enforces that 
    // only StreamingSettings or a derived class will be valid generic arguments!
public class FunkyDevice<TStreamingSettings> where TStreamingSettings : StreamingSettings
{
    public virtual VideoStream openVideoStream(TStreamingSettings settings)
    {
        if (openVideoStreams < 2)
        {
            openVideoStreams++;
            return new VideoStream(...);
        }
    }
    public virtual AudioStream openAudioStream(TStreamingSettings settings)
    {
        if (openAudioStreams < 1) 
        {
            openAudioStreams++;
            return new AudioStream(...);            
        }
    }
}

和:

public class UserSession : FunkyDevice<UserStreamingSettings>
{
    public override VideoStream openVideoStream(UserStreamingSettings settings)
    {
        // Do some custom stuff
        // Call here the base class' implementation
        base.openVideoStream(...);
        // Do some custom stuff
    }
    public override AudioStream openAudioStream(UserStreamingSettings settings)
    {
        // Do some custom stuff
        // Call here the base class' implementation
        base.openAudioStream(...);
        // Do some custom stuff
    }
}

总之:

  • 泛型和继承一起为您提供代码重用。
  • 多态性使您有机会重用基类实现并覆盖它们以满足更具体的要求。

一些注意事项:.NET 约定建议方法使用帕斯卡大小写!

  • :openVideoStream
  • 好的:打开视频流
于 2013-08-08T10:15:10.227 回答