0

C#。我有一个名为FileProcessor

class FileProcessor {
    public Path {get {return m_sPath;}}

    public FileProcessor(string path) 
    {
        m_sPath = path;
    }

    public virtual Process() {}

    protected string m_sath;
}

现在我想创建其他类ExcelProcessor& PDFProcessor

class Excelprocessor: FileProcessor 
{
    public void ProcessFile()
    {
        //do different stuff from PDFProcessor
    }
}

同样PDFProcessor,如果路径以“.xlsx”结尾,则文件为 Excel,如果以“.pdf”结尾,则为 pdf。我可以ProcessingManager上课:

class ProcessingManager
{
    public void AddProcessJob(string path)
    {
        m_list.Add(Path;)
    }

    public ProcessingManager()
    {
        m_list = new BlockingQueue();
        m_thread = new Thread(ThreadFunc);
        m_thread.Start(this);
    }

    public static void ThreadFunc(var param) //this is a thread func
    {
        ProcessingManager _this = (ProcessingManager )var;
        while(some_condition) {
            string fPath= _this.m_list.Dequeue();
            if(fPath.EndsWith(".pdf")) {
                new PDFProcessor().Process();
            }
            if(fPath.EndsWith(".xlsx")) {
                new ExcelProcessor().Process();
            }
        }
    }

    protected BlockingQueue m_list;
    protected Thread m_thread;
}

我试图使其尽可能模块化,例如,假设我想添加一个“.doc”处理,我必须在管理器内部进行检查并实现另一个DOCProcessor. 如果不修改 ,我怎么能做到这一点ProcessingManager?我真的不知道我的经理是否足够好,请告诉我您对此的所有建议。

4

5 回答 5

3

我不是很清楚你的问题,但我会尝试试一试。

您可能正在使用工厂模式。

class FileProcessorFactory {
    public FileProcessor getFileProcessor(string extension){
        switch (extension){
            case ".pdf":
                return new PdfFileProcessor();
            case ".xls":
                return new ExcelFileProcessor();
        }
    }
}

class IFileProcessor{
    public Object processFile(Stream inputFile);
}

class PdfFileProcessor : IFileProcessor {
    public Object processFile(Stream inputFile){
        // do things with your inputFile
    }
}

class ExcelFileProcessor : IFileProcessor {
    public Object processFile(Stream inputFile){
        // do things with your inputFile
    }
}

这应该确保您使用 FileProcessorFactory 来获取正确的处理器,并且 IFileProcessor 将确保您没有为每个处理器实现不同的东西。

并实现另一个 DOCProcessor

只需向 中添加一个新案例FileProcessorFactory,以及一个实现IFileProcessor名为的接口的新类DocFileProcessor

于 2013-06-10T15:54:17.890 回答
2

您可以使用如下自定义属性来装饰您的处理器:

[FileProcessorExtension(".doc")]
public class DocProcessor()
{

}

然后,您的处理管理器可以找到其 FileProcessorExtension 属性与您的扩展匹配的处理器,并自反地实例化它。

于 2013-06-10T15:50:20.063 回答
1

使用另一种方法CanHandle,例如:

abstract class FileProcessor 
{
    public FileProcessor() 
    {
    }

    public abstract Process(string path);
    public abstract bool CanHandle(string path);
}

使用excel文件,您可以实现CanHandle如下:

class Excelprocessor: FileProcessor 
{
    public override void Process(string path)
    {
    }

    public override bool CanHandle(string path)
    {
        return path.EndsWith(".xlsx");
    }
}

ProcessingManager中,您需要一个处理器列表,您可以通过以下方法在运行时添加它RegisterProcessor

class ProcessingManager
{
    private List<FileProcessor> _processors;

    public void RegisterProcessor(FileProcessor processor)
    {
        _processors.Add(processor)
    }
    ....

所以可以在这里使用 LINQ 来找到合适的处理器:

while(some_condition) 
{
     string fPath= _this.m_list.Dequeue();

     var proccessor = _processors.SingleOrDefault(p => p.CanHandle(fPath));
     if (proccessor != null)
         proccessor.Process(proccessor);
}

如果要添加更多处理器,只需ProcessingManager使用 RegisterProcessor方法定义并添加即可。FileProcessorFactory即使像@Highmastdon's answer ,您也不会更改其他类的任何代码。

于 2013-06-10T16:09:04.210 回答
1

我同意 Highmastdon 的观点,他的工厂是一个很好的解决方案。核心思想是在您的 ProcessingManager 中不再有任何 FileProcessor 实现引用,只有对 IFileProcessor 接口的引用,因此 ProcessingManager 不知道它处理的是哪种类型的文件,它只知道它是一个实现 processFile(Stream inputFile) 的 IFileProcessor .

从长远来看,您只需要编写新的 FileProcessor 实现,瞧。ProcessingManager 不会随着时间而改变。

于 2013-06-10T16:12:47.953 回答
1

您可以使用工厂模式(一个不错的选择)

  1. 在工厂模式中,可以不更改现有代码(遵循 SOLID 原则)。
  2. 将来如果要添加新的 Doc 文件支持,您可以使用字典的概念。(而不是修改switch语句)

    //Some Abstract Code to get you started (Its 2 am... not a good time to give a working code)
     1. Define a new dictionary with {FileType, IFileProcessor)
     2. Add to the dictionary the available classes.
     3. Tomorrow if you come across a new requirement simply do this.
         Dictionary.Add(FileType.Docx, new DocFileProcessor());
     4. Tryparse an enum for a userinput value. 
     5. Get the enum instance and then get that object that does your work!
    

否则一个选项:最好使用 MEF(托管可扩展性框架!)

这样,您就可以动态地发现这些类。

例如,如果需要实现对 .doc 的支持,您可以使用如下内容:

Export[typeof(IFileProcessor)]
class DocFileProcessor : IFileProcessor
{
    DocFileProcessor(FileType type);

    /// Implement the functionality if Document type is .docx in processFile() here
}

这种方法的优点:

  1. 您的 DocFileProcessor 类会自动识别,因为它实现了 IFileProcessor
  2. 应用程序始终是可扩展的。(您对所有部分执行一次 importOnce,获取匹配的部分并执行 .. 就这么简单!)
于 2013-06-10T20:00:12.623 回答