0
Answer

Which approach is better according to OOP principals?

mahdi gh

mahdi gh

7y
331
1

I'm trying to understand OOP SOLID principals and Design patterns. Here is a sample scenario Which I'm practicing with. Consider a media convertor app which accepts video, audio and photo files and each type has it's own different implementations of convert and different output extension. Properties like Id, FileName and Type is common but each type could have specific properties. for example Video file has video codec. I defined a base class which contains common properties. Here is my class:

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 }` 

But I don't know should I define an abstract method named convert inside this class and override it into subclasses or I should define a separate interface for handling convert process according separation of concerns principal. I have defined my models into a separate assembly (should I?) and if I put another interface put in charge of convert process, if convert process needs to be changed, there will be no changes and no recompile to domain models assembly. but if I simply add an abstract method, implementing the class would be easier and less code is needed. I have uploaded two approaches that I took. Please if you can check them and clarify What I'm doing wrong? I want to follow SOLID principals and also Abstract design pattern. Thanks link to download sample projects

some of the code is like this:

  1. public abstract class MediaFile  
  2.        {  
  3.            public abstract string OutputExtension { get; }  
  4.            public int Id { getset; }  
  5.            public string FileName { getset; }  
  6.            public MediaType Type { getset; }  
  7.        }  
  8.        public enum MediaType { Video, Audio, Photo }  
  9.   
  10.        public class VideoMedia : MediaFile  
  11.        {  
  12.            private readonly string _outputExtension;  
  13.            public override string OutputExtension { get { return _outputExtension; } }  
  14.            // specefic fields for video media           
  15.            public string VideoCodec { getset; }  
  16.            public string Duration { getset; }  
  17.            public VideoMedia() { _outputExtension = "mp4"this.Type = MediaType.Video; }  
  18.        }  
  19.        public class PhotoMedia : MediaFile  
  20.        {  
  21.            private readonly string _outputExtension;  
  22.            public override string OutputExtension { get { return _outputExtension; } }  
  23.            //specefic fields for photo media   
  24.            public int Height { getset; }  
  25.            public int Width { getset; }  
  26.            public PhotoMedia()  
  27.            { _outputExtension = "jpg"this.Type = MediaType.Photo; }  
  28.            public string Resolution  
  29.            { get { return Width.ToString() + "x" + Height.ToString(); } }  
  30.        }  
  31.   
  32.        //one approach is like this    
  33.        public interface IMediaConvertor { MediaFile Media { get; } void Convert();  }  
  34.        public class VideoConvertor : IMediaConvertor  
  35.        {  
  36.            private VideoMedia _media;  
  37.            public VideoConvertor(VideoMedia media) { _media = media; }  
  38.            public MediaFile Media { get { return _media; } }  
  39.            public void Convert()  
  40.            {  
  41.                Console.WriteLine("Converting a Video named {0} [VideoCodec={1}] to {2}", _media.FileName, _media.VideoCodec, _media.OutputExtension);  
  42.            }  
  43.        }  
  44.        public class PhotoConvertor : IMediaConvertor  
  45.        {  
  46.            private PhotoMedia _media;  
  47.            public PhotoConvertor(PhotoMedia media) { _media = media; }  
  48.            public void Convert()  
  49.            {  
  50.                Console.WriteLine("Converting a Photo named {0} [Resolution={1}] to {2}", _media.FileName, _media.Resolution, _media.OutputExtension);  
  51.            }  
  52.            public MediaFile Media { get { return _media; } }  
  53.        }  
  54.   
  55.        public class MediaConvertorFactory  
  56.        {  
  57.            public IMediaConvertor GetConvertor(MediaFile media)  
  58.            {  
  59.                if (media.Type == MediaType.Video)               
  60.                    return new VideoConvertor(media as VideoMedia);   
  61.                if (media.Type == MediaType.Audio)   
  62.                        return new AudioConvertor(media as AudioMedia);  
  63.                return new PhotoConvertor(media as PhotoMedia);  
  64.            }  
  65.        }  
  66.   
  67.        class Program  
  68.        {  
  69.            static void Main(string[] args)  
  70.            {  
  71.                var mediafiles = new List<MediaFile>();   
  72.                mediafiles.Add(new AudioMedia() { FileName = "test-audio.wav", AudioBitrate = 64 });  
  73.                mediafiles.Add(new VideoMedia() { FileName = "test-video.avi", VideoCodec = "H.264" });  
  74.                mediafiles.Add(new PhotoMedia() { FileName = "test-photo.bmp", Width = 1024, Height = 764 });  
  75.                mediafiles.Add(new VideoMedia() { FileName = "test-video2.mkv", VideoCodec = "Xvid" });  
  76.   
  77.                foreach (var media in mediafiles)  
  78.                {  
  79.                    MediaConvertorFactory factory = new MediaConvertorFactory(); factory.GetConvertor(media).Convert();  
  80.                }   
  81.                Console.ReadKey();  
  82.            }  
  83.        }   
  84.          
  85.        //another approach is to add abstract method to base class and overide it which you can see in my project files