简体   繁体   中英

How to determine which implementation of an abstract class to use?

What would be the best way to determine which implementation of an abstract class to call based on a certain variable or defining feature?

Code Example:

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

I feel as though there is a "smarter" way to do this with the use of better OO concepts. The code I wrote up is an example to demonstrate what I am trying to understand, sorry if there are simple errors but the basic idea is there. I know this is a specific example, but I think this applies to many other types of problems too.

I would recommend using a factory to retrieve your processor:

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

Then your factory is something like:

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

Note that we are using an interface, which your abstract class would inherit from. This allows any of your inheriting types to be returned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM