0

動画ファイル変換エンジンを設計しています。

さまざまなソースがあります (開始/終了タイム コードを含むファイル、プレイリスト ファイル、入力ファイルを記述したさまざまなテキスト/XML ファイル、およびこれらのファイルに適用するビデオ/オーディオ エフェクトなど)。

さまざまな出力 (ファイルまたはコマンド テキスト ファイル) があります。

変換を行うために実行するさまざまなツール (主に dos コマンド) があります。

新しいソースまたは新しい出力を簡単に追加/変更できるように、オープン/クローズの原則に従うエンジンを設計したいと考えています。

多くのクラスを持たないようにしたいので、継承はオプションではないと思います。

中央クラスのコンバーターを作成することを考えました。

エンジンは、ソースからこの Converter クラスを作成し、ソースを出力に変換します。

それが良いアプローチかどうかはわかりません。

戦略パターンを確認しましたが、これが適切なパターンであるかどうかはわかりません。

4

3 に答える 3

2

これにアプローチする主な方法は 2 つあります。どちらも戦略パターンに基づいています。

  1. 入力と出力の間で変換する入力と出力のすべての順列のクラスを作成し、それらを中央の Converter クラスを持つ戦略パターンに配置します。このクラスは、見つけた、または与えられた実装のコレクションから正しい実装を選択できます。

    • 利点はシンプルさです。既存の各実装は、機能したら、追加の入力または出力タイプの追加に基づいて変更するために「クローズ」する必要があります。
    • 欠点は、5 つの入力と 2 つの出力の場合、10 の実装が必要になることです。3 番目の出力を追加するには、入力ごとに 1 つずつ、さらに 5 つのクラスを作成する必要があります。また、おそらく頻繁に繰り返します。これらすべてのクラスを抽象ベースから派生させることを検討してください。これを使用して、共通コードを 1 か所に「プルアップ」できます。
  2. 出力を生成するために必要なすべての情報を含む、特定の入力を中間のメモリ内形式に変換できる各入力のクラスを作成します。次に、特定の入力変換によって生成された中間体を指定して、出力を生成する各出力のクラスを作成します。これらすべてを、特定の状況で必要に応じて入力変換と出力変換を「組み合わせて一致させる」中央のコンバーターに入れます。

    • 利点は、新しい出力タイプを追加しても、入力タイプと同じ数の実装を作成する必要がないことです。逆も同様です。また、コードの繰り返しも少なくなります。任意の入力を中間に変換する方法は 1 つと、中間を特定の出力に変換する方法が 1 つあります。そのため、2 つの異なる実装で同じメソッド呼び出しを行っていることに気付くべきではありません (ただし、実装は抽象から派生する可能性があります)。共有コードを許可するベース)。
    • 欠点は、内部の複雑さが増し、変化に敏感になることです。中間タイプは必須ですが、コードの外部でそれを使用することはなく、中間タイプに格納する必要がある情報の量が変化した場合 (たとえば、現在入力から提供している情報よりも多くの情報を必要とする新しい出力をサポートする場合など) )、戻って既存の作業コードを変更し、反対側で必要になる新しいデータを追加する必要があります。

どちらがうまく機能するかは、このシステムがどのような変化を遂げなければならないと予測するかによって異なります。新しいタイプの入力または出力が追加されると予想される場合は、クラス数が減るため、仲介者の方が適切なパターンになります (5 つの入力、3 つの出力は 15 ではなく 8 つのコンバーターです)。ただし、仲介者も Open/Closed の原則に従っていることを確認する必要があります。そのため、新しいデータを提供または消費する必要がある入力または出力の新しい実装を追加し、仲介者を拡張できます。既存の実装を完全に壊したり、入力と出力の組み合わせに互換性がありません。データの種類や量を予測する場合は、データを取得または出力する方法以上の変更が必要になるでしょう。または、各入力と出力の間で大幅に異なる変換プロセスが予測される場合は、

于 2012-04-10T16:23:18.333 に答える
1

パターンの組み合わせと、パターンではないコードの実用的なアプリケーションが必要になる可能性があります。戦略パターンは、「これをロード/書き込むにはどうすればよいですか?」を入力するのに適しています。複合パターンは、「これらの要素をつなぎ合わせる」または「この遷移効果を実行する」のに適しています。デコレータパターンは、ビデオの上にエフェクトを適用するのに適しています。

こだわりは、意味のある方法で実装および装飾できる共通のインターフェースを提供することです。実装しようとしている動作について詳しく知らなければ、言うのは難しいです。

于 2012-04-10T16:19:04.357 に答える
1

Pierre からのコメントに従って更新します。

ジェネリック コンバーターを次のように定義します。

public interface IVideoConverter
{
     IInputReader  Reader {get;set;}
     IOutputWriter Writer {get;set;}
     void Convert();
}

インターフェイスを定義します。

public interface IInputReader
{
    bool IsSUpported(string inputId);

    void AppendToBuffer(Buffer buffer);
}

public interface IOutputWriter
{
    bool IsSUpported(string outputId);

    void WriteFromBuffer(Buffer buffer);
}

コンバーターを実装するクラスを作成します。

public class VideoConverter : IVideoConverter
{
   ...       
}

3つの工場を書く:

public class InputReaderFactory
{
   public IInputReader GetReader(string inputId)
   {
       ...
   }
}

public class OutputWriterFactory
{
   public IOutputWriter GetWriter(string outputId)
   {
      ...
   }
}

public class VideoConverterFactory
{
   public IVideoConverter GetConverter(string inputId, string outputId)
   {
      ...
   } 
}

各ファクトリで、ファクトリが担当するインスタンスを構築する任意のメソッドを使用します。VideoConverterFactory はリーダー ファクトリとライター ファクトリを使用する必要があります。

具体的な型の初期化を実装するには、いくつかの方法があります。2について説明します。

a) サポートされているすべてのタイプの静的読み取り専用配列またはリストを作成し、このリストで、指定された入力パラメーターをサポートする最初のコンバーターを検索します。

 public class InputReaderFactory
 {
   private static readonly IEnumerable<IInputReader> SupportedReaders = new IInputReader[] {new Reader1(), new Reader2(),....}
   public IInputReader GetReader(string inputId)
   {
      for(int i=0; i<SupportedReaders .length; i++)
      {
        if(SupportedReaders [i].IsSupported(inputId)
          return SupportedReaders [i];
      }

      return null;
   }
}

b)構成ファイルでサポートされているタイプを定義し(構成要素、構成コレクション、およびそのセクションを実装します)、ファクトリクラスで構成からサポートされているコンバーターを検索し、見つかったらリフレクションを使用してインスタンスを作成します

于 2012-04-10T16:34:20.447 に答える