Unity3D と C# でメディア プレーヤー アプリケーションを作成しています。
(私の質問は Unity とは関係ありません。純粋な設計上の問題です)
これが私が現在持っているものです:
IApp
実装者とのインターフェース:TextViewer
ImageViewer
MediaPlayer
IFile
実装者とのインターフェース:TextFile
ImageFile
MediaFile
- 子供たちと:VideoFile
AudioFile
インターフェースは次のとおりです。
public interface IApp
{
void Open(IFile file);
Type SupportedType { get; }
}
各アプリには、開くことができる特定のサポートされているファイルの種類があります。
私の についての言葉はMediaPlayer
、オーディオとビデオの両方のファイルを開いたり再生したりできるということです。しかし、ビデオを開く方法は、オーディオを開く方法とは異なるため、それぞれに固有のロジックがあります。
コードは次のとおりです。非常に単純です (ただし、まだ完全には実装されていません)。
public class MediaPlayer : IApp
{
public Type SupportedType { get { return typeof(MediaFile); } }
public void Open(IFile file)
{
if (file is MediaFile)
Console.WriteLine("MediaPlayer opening media file...");
}
List<MediaFile> Medias = new List<MediaFile>();
public MediaFile Current { private set; get; }
public PlaybackControls Controls { private set; get; }
public PlaybackSettings Settings { private set; get; }
public MediaPlayer()
{
Controls = new PlaybackControls(this);
Settings = new PlaybackSettings(this);
}
public class PlaybackControls
{
private MediaPlayer player;
private int index;
public PlaybackControls(MediaPlayer player)
{
this.player = player;
}
public void Seek(float pos) { }
public void Next()
{
index = (index + 1) % player.Medias.Count;
player.Current = player.Medias[index];
}
public void Previous()
{
index--;
if (index < 0)
index = player.Medias.Count - 1;
player.Current = player.Medias[index];
}
private void PlayVideo(VideoFile video)
{
// video logic
}
private void PlayAudio(AudioFile audio)
{
// audio logic
}
public void Play(MediaFile media)
{
IsPlaying = true;
if (media is AudioFile)
PlayAudio(media as AudioFile);
else if (media is VideoFile)
PlayVideo(media as VideoFile);
}
public void Play()
{
Play(player.Current);
}
public void Pause()
{
IsPlaying = false;
}
public void Stop()
{
IsPlaying = false;
Seek(0);
}
public bool IsPlaying { get; private set; }
}
public class PlaybackSettings
{
// Volume, shuffling, looping, etc
}
}
私があまり好きではないことは、Play(Media)
方法です。内部では、メディア タイプのチェックを行っており、メディアがビデオかオーディオかに応じて、適切なメソッドを呼び出しています。私はそれが好きではない、私はそれがまったく正しいとは思わない。写真のような他の種類のメディアがあった場合はどうなりますか? ImageFile
の下に移動したい場合はどうすればよいMediaFile
ですか? else-if
次に、ポリモーフィックではない別のステートメントを追加する必要があります。
代わりにできることは、次のように、メディア ファイルに呼び出すメソッドを選択させることです。
public abstract class MediaFile : IFile
{
//...
public abstract void Open(MediaPlayer from);
//...
}
public class AudioFile : MediaFile
{
public override void Open(MediaPlayer from)
{
from.PlayAudio(this);
}
}
public class VideoFile : MediaFile
{
public override void Open(MediaPlayer from)
{
from.PlayVideo(this);
}
}
今ではMediaPlayer
:
public void Open(MediaFile media)
{
media.Open(this); // polymorphically open it
}
他に何もありません-if、いいね!しかし、これは私が好きではない他の不都合をもたらします:
VideoFile
&MediaPlayer
とAudioFile
&MediaPlayer
はより密結合になりました。- 現在、循環依存関係があります(
MediaPlayer
知っておく必要がAudio/VideoFile
あり、その逆も同様です) Audio/VideoFile
sが自分で自分で開くことができるのは意味がないと思います(実際にはそうしていませんが、MediaPlayer
開く方法を教えているだけです。sは方法MediaPlayer
を知っているはずです、彼は知りません.彼の仕事のやり方を誰かに教えてもらう必要はない.)- それは非常に冗長に感じます。誰かに耳を指すように頼むようなものです。そのため、彼は右手を頭に巻き付け、右耳ではなく左耳を指します。-何が起こっているかというと、
また
MediaPlayer.Open(Media) -> AudioFile.Open(AudioFile) -> MediaPlayer.OpenAudio(AudioFile)
また
MediaPlayer.Open(Media) -> VideoFile.Open(VideoFile) -> MediaPlayer.OpenVideo(VideoFile)
私たちは、ポリモーフィズムの名の下に、正しいメソッドに直接行くことができたはずの自分自身の周りをぐるぐる回っています。
上記の 2 つのアプローチはどちらも最適ではないと思いますが、どちらかを選択する場合は、最初のアプローチを選択します。
どう思いますか?より良い方法はありますか?- すべての鳥を 1 つの石で撃つ、素晴らしく、エレガントで堅牢なポリモーフィックな方法は? これについてどうすればよかったですか?ここで使用できるデザインパターンがあるかもしれません。
また、私の判断が間違っていた場合は、訂正してください。
事前に助けてくれてありがとう。