我正在尝试了解OOP SOLID主体和设计模式。这是我正在练习的示例场景。考虑一个媒体转换器应用程序,它接受视频,音频和照片文件,每种类型都有自己不同的转换实现和不同的输出扩展。 Id,FileName和Type等属性很常见,但每种类型都可以具有特定属性。例如,视频文件具有视频编解码器。我定义了一个包含公共属性的基类。这是我的班级:
public abstract class MediaFile
{
public abstract string OutputExtension { get; }
public int Id { get; set; }
public string FileName { get; set; }
public MediaType Type { get; set; }
}
public enum MediaType
{
Video,
Audio,
Photo
}`
但是我不知道我应该在这个类中定义一个名为convert的抽象方法并将其覆盖到子类中,或者我应该根据关注点principal的分离来定义一个单独的接口来处理转换过程。我已经将我的模型定义为一个单独的程序集(我应该吗?)如果我将另一个接口负责转换过程,如果需要更改转换过程,则不会有任何更改,也不会重新编译到域模型程序集。但是如果我只是添加一个抽象方法,那么实现该类将更容易,并且需要更少的代码。我上传了两种方法。如果你能检查一下并澄清我做错了什么?我想遵循SOLID原则和抽象设计模式。谢谢 link to download sample projects
一些代码是这样的:
public class VideoMedia:MediaFile
{
private readonly string _outputExtension;
public override string OutputExtension
{
get { return _outputExtension; }
}
// specefic fields for video media
public string VideoCodec { get; set; }
public string Duration { get; set; }
public VideoMedia()
{
_outputExtension = "mp4";
this.Type = MediaType.Video;
}
}
public class PhotoMedia : MediaFile
{
private readonly string _outputExtension;
public override string OutputExtension
{
get { return _outputExtension; }
}
//specefic fields for photo media
public int Height { get; set; }
public int Width { get; set; }
public PhotoMedia()
{
_outputExtension = "jpg";
this.Type = MediaType.Photo;
}
public string Resolution
{
get { return Width.ToString() + "x" + Height.ToString(); }
}
}
//one approach is like this
public interface IMediaConvertor
{
MediaFile Media { get; }
void Convert();
}
public class VideoConvertor:IMediaConvertor
{
private VideoMedia _media;
public VideoConvertor(VideoMedia media)
{
_media = media;
}
public MediaFile Media
{
get { return _media; }
}
public void Convert()
{
Console.WriteLine("Converting a Video named {0} [VideoCodec={1}] to {2}", _media.FileName, _media.VideoCodec, _media.OutputExtension);
}
}
public class PhotoConvertor: IMediaConvertor
{
private PhotoMedia _media;
public PhotoConvertor(PhotoMedia media)
{
_media = media;
}
public void Convert()
{
Console.WriteLine("Converting a Photo named {0} [Resolution={1}] to {2}", _media.FileName, _media.Resolution, _media.OutputExtension);
}
public MediaFile Media
{
get { return _media; }
}
}
public class MediaConvertorFactory
{
public IMediaConvertor GetConvertor(MediaFile media)
{
if (media.Type == MediaType.Video)
return new VideoConvertor(media as VideoMedia);
if (media.Type == MediaType.Audio)
return new AudioConvertor(media as AudioMedia);
return new PhotoConvertor(media as PhotoMedia);
}
}
class Program
{
static void Main(string[] args)
{
var mediafiles = new List<MediaFile>();
mediafiles.Add(new AudioMedia() { FileName = "test-audio.wav", AudioBitrate = 64 });
mediafiles.Add(new VideoMedia() { FileName = "test-video.avi", VideoCodec = "H.264" });
mediafiles.Add(new PhotoMedia() { FileName = "test-photo.bmp", Width = 1024, Height = 764 });
mediafiles.Add(new VideoMedia() { FileName = "test-video2.mkv", VideoCodec = "Xvid" });
foreach (var media in mediafiles)
{
MediaConvertorFactory factory = new MediaConvertorFactory();
factory.GetConvertor(media).Convert();
}
Console.ReadKey();
}
}
//another approach is to add abstract method to base class and overide it which you can see in my