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(...);            
        }
    }
}

ただし、今は複数のデバイスをサポートする必要があります。これらをユーザー セッションにグループ化します。すべてのユーザー セッションは、各ストリームの数も制限しますが、もちろん、これらの数はデバイスの制限と同じではありません (そうでなければ、問題は簡単すぎます)。たとえば、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);     
        }
    }
}

ご覧のとおり、 と のパブリック インターフェイスFunkyDeviceUserSessionほぼ同じですが、 のすべてのメソッドに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
  • OK: ビデオストリームを開く
于 2013-08-08T10:15:10.227 に答える