C# 寻找一种[可能的]设计模式

C# 寻找一种[可能的]设计模式,c#,design-patterns,C#,Design Patterns,这是我的设想。用户在我的软件中选择一个文档,我的软件从文档中提取一些关键数据。软件处理两种格式;PDF和DOCX。对于每种类型,都有多个模板,并且上传的文档应该属于其中一个模板。我不知道这是否是一个众所周知的问题,也不知道是否存在一个既定的设计模式来解决这个场景(这就是为什么我这么认为)。以下是我迄今为止所设计的: 因为每个模板都有特定的结构/内容,所以我考虑为每个模板创建单独的类。将有一个名为IExtractor的顶级接口,然后将有两个名为PdfExtractor和DocxExtractor的

这是我的设想。用户在我的软件中选择一个文档,我的软件从文档中提取一些关键数据。软件处理两种格式;PDF和DOCX。对于每种类型,都有多个模板,并且上传的文档应该属于其中一个模板。我不知道这是否是一个众所周知的问题,也不知道是否存在一个既定的设计模式来解决这个场景(这就是为什么我这么认为)。以下是我迄今为止所设计的:

因为每个模板都有特定的结构/内容,所以我考虑为每个模板创建单独的类。将有一个名为IExtractor的顶级接口,然后将有两个名为PdfExtractor和DocxExtractor的顶级类,每个类都实现了IExtractor接口。所有PDF(或DOCX)模板共有的任何功能都将进入这些父类

在这两个父类下面,将有几个模板类,每个模板一个。例如,一个名为Template571_PdfExtractor的类继承自PdfExtractor,它具有特定于模板571的方法,但以与任何其他提取器相同的形式提供结果

如果有必要的话,我正在使用C#4.0。这是骨架:

界面:

interface IExtractor
{
void ExtractDocument(System.IO.FileInfo document, dsExtract dsToFill);
}
两个父类:

public class DocxExtractor : IExtractor 
{
    public virtual void ExtractDocument(System.IO.FileInfo document, dsExtract dsToFill)
    {
    }
}

public class PdfExtractor : IExtractor 
{
    public virtual void ExtractDocument(System.IO.FileInfo document, dsExtract dsToFill)
    {
    }
}
混凝土类别之一:

public class Template571_PdfExtractor : PdfExtractor
{
    public virtual void ExtractDocument(System.IO.FileInfo document, dsExtract dsToFill)
    {
    }
}
现在有几个关键问题我不确定。所有这些都围绕着一个问题,我不知道如何以及在哪里实例化具体(模板)类的对象。我可以使用文件扩展名来决定是否需要进入PdfExtractor树节点或DocxExtractor节点。之后,文件的内容告诉我用户文档所属的模板。那么我应该把这个“决定”代码放在哪里呢?我的想法是把它放在PdfExtractor类(或者是DocxExtractor)。这是正确的方法吗

对不起,我说得有点长,但我不知道如何充分描述我的情况。谢谢你的想法


Shujaat

一旦你深入研究设计模式,你肯定会发现大多数时候没有一种正确的方法来实现某些东西

一种可能的方法是创建所谓的工厂类:一个用于pdfextractor,另一个用于docxextractor。每个工厂类可能都有一个静态方法,如

public final class PdfExtractorFactory {
   public static PdfExtractor getExtractor(String filename) { ... }

   ... // constructor, or singleton getter here
}
决定要返回的PdfExtractor实例的具体子类(即使用哪个模板)的逻辑将驻留在工厂方法中。这样,抽象基类PdfExtractor及其子类都不会被这种决策逻辑弄得乱七八糟。只有工厂类需要知道PdfExtractor(resp.DocXExtractor)的子类,而代码的其余部分将完全不知道具体的子类,因为工厂传递超类的实例

由于您可能只需要PdfExtractorFactory和DocXExtractorFactory的一个实例,因此您可以选择将这些工厂类实现为单例


更新:当然,您可以使用静态工厂方法,也可以使用单例模式和非静态工厂方法(但您不需要两者)。

谢谢Valentin。这确实很有帮助。如果没有更好的方法,我会尝试一下,并将其标记为答案。在我实现这一点的过程中,有一点是:有没有一个很好的理由让我选择Singleton模式而不是静态方法,如您上面所示?至少在这种情况下,静态方法不如单例类好吗?更重要的是,factory类的方法GetExtractor需要检查pdf(或docx)文件的内容,以确定它属于哪个模板。另一方面,所有具体类也需要相同的功能(从pdf文件读取内容),因为它们将对这些内容进行实际解析。因此,我计划将ReadContents()函数添加到PdfExtractor类中。您认为工厂类如何在不破坏模式和OO规则的情况下使用此函数?关于双重解析:我会尝试将所有解析代码保留在工厂类中(即,模板子类只保存数据并提供getter,但不知道如何从文件解析自己-考虑高内聚性)。这样,工厂将只解析一次文件,并在最后调用相应模板类的构造函数。您还可以重新考虑为所有模板创建不同子类的决定——也许您可以只使用通用的PdfExtractor类,工厂将根据当前模板结构添加“内容部分”。