2014-02-12 73 views
0

根據某個變量或定義特徵來確定抽象類的哪個實現需要調用的最佳方法是什麼?如何確定要使用哪個抽象類的實現?

代碼示例:

public abstract class FileProcesser 
{ 
    private string _filePath; 

    protected FileProcessor(string filePath) 
    { 
     if (filePath == null) 
     { 
      throw new ArgumentNullException("filePath"); 
     } 

     // etc etc 

     _filePath = filePath; 
    } 

    // some example methods for this file 
    public abstract int GetFileDataCount(); 
    public abstract IEnumerable<FileItem> GetFileDataItems(); 
} 

// specific implementation for say, a PDF type of file 
public class PdfFileProcesser : FileProcessor 
{ 
    public PdfFileProcessor(string filePath) : base(filePath) {} 

    // implemented methods 
} 

// specific implementation for a type HTML file 
public class HtmlFileProcessor : FileProcessor 
{ 
    public HtmlFileProcessor(string filePath) : base(filePath) {} 

    // implemented methods 
} 

public class ProcessMyStuff() 
{ 
    public void RunMe() 
    { 
     // the code retrieves the file (example dummy code for concept) 
     List<string> myFiles = GetFilePaths(); 

     foreach (var file in myFiles) 
     { 
      if (Path.GetExtension(file) == ".pdf") 
      { 
       FileProcessor proc = new PdfFileProcessor(file); 
       // do stuff 
      } 
      else if (Path.GetExtension(file) == ".html") 
      { 
       FileProcessor proc = new HtmlFileProcessor(file); 
       // do stuff 
      } 
      // and so on for any types of files I may have 
      else 
      { 
       // error 
      } 
     } 
    } 
} 

我覺得好像有一個「聰明」的方式配合使用,更好地面向對象的概念來做到這一點。我編寫的代碼是一個示例,用於說明我想要理解的內容,如果存在簡單的錯誤但基本思想存在,則很抱歉。我知道這是一個具體的例子,但我認爲這也適用於許多其他類型的問題。

+1

看看「抽象工廠模式」。 – EkoostikMartin

+3

這幾乎是工廠的基本情況。 http://www.dotnetperls.com/factory –

+0

您似乎正在實施戰略模式。我更傾向於創建一個Processor類,它包含一個IProcessFiles接口,該接口定義所涉及的基本方法,併爲每種類型單獨運行處理器,每個處理器只查找可處理的文件類型。這可能效率較低,但它更乾淨。 – Magus

回答

0

我會建議使用一個工廠來檢索您的處理器:

foreach (var file in myFiles) 
    { 
     string extension = Path.GetExtension(file); 
     IFileProcessor proc = FileProcessorFactory.Create(extension); 
     // do stuff 
    } 

那麼你的工廠是一樣的東西:

public static class FileProcessorFactory 
{ 
    public static IFileProcessor Create(string extension) { 
     switch (extension) { 
      case "pdf": 
       return new PdfFileProcessor(); 
      case "html": 
       return new HtmlFileProcessor(); 
      // etc... 
     } 
    } 
} 

請注意,我們使用的接口,你的抽象類將繼承從。這允許返回任何繼承類型。

+0

公平地說,這只是移動if鏈,並且不會很好地適應其他策略。任何新的FileProcessor將需要在工廠中重新編譯程序集,然後添加新的「case」。 – Magus

+1

我同意mayabelle。如果你的處理器和工廠方法在lib A和lib B中添加新處理器,那麼就讓B有自己的工廠方法,如果在A中找不到任何東西,就調用它的A和後備處理器。 或者,您可以將屬性置於處理器類與他們的擴展,並使用反射來選擇正確的......但坦率地說,我懷疑它是值得的。或者你可以將之前的轉換成全局字典......但有時候,如果不是那麼糟糕,那麼有時候會很好。 –