简体   繁体   中英

Constructor arguments for Factory in C#, am I doing it right?

I have explained my problem below, my question is: 1. Whether I'm right in using factory pattern to this problem 2. Am I doing it right?

I have what you can call an incident tracker system which is used in construction sites by workers/managers, it's developed in ASP.NET MVC, the application stores different types of incidents that occurred at different locations. Now I have to provide a way for the user to generate reports based on locations, incident type etc.

This is how I'm doing it in my code (have included comments instead of code in some parts for brevity) -

//Controller methods
public ActionResult ReportByLocation(){
    var incidents = GetDataFromRepo();
    var reportFactory = new IncidentReportFactory(incidents, "ByLocation");
    var pdfView = new ReportsGenerator(reportFactory).GetPdfView();
    return pdfView;
}

public ActionResult ReportByType(){
    var incidents = GetDataFromRepo();
    var reportFactory = new IncidentReportFactory(incidents, "ByType");
    var pdfView = new ReportsGenerator(reportFactory).GetPdfView();
    return pdfView;
}

//Concrete factory class
public class IncidentReportFactory : ReportFactory{
    public IncidentFactory(List<Incident> incidents, string reportType){
        //Initialize properties
    }

    public ConcreteReport CreateConcreteReport(){
        switch(ReportType){
            case "ByLocation": return new IncidentLocationReport(incidents);
                               break;
            case "ByType": return new IncidentTypeReport(incidents);
                           break;
        }
    }
}

//ConcreteReport class
public class IncidentLocationReport : ConcreteReport{
    public IncidentLocationReport(List<Incident> incidents){
         //Constructor which sorts, splits, etc. based on location 
         //and returns
    }
}

//Report generator class
public ReportsGenerator{
     public ReportsGenerator(ReportFactory factory){
           Factory = factory;
     }

     public PDFView GetPdfView(){
          var report = factory.CreateConcreteReport();
          var pdfView = ConstructPdfWithAllFormatting(report);
          return pdfView;
     }
}

Also note that I'm inheriting from abstract factory and concrete classes Does my code makes any sense? Or am I doing it all wrong? Please point me in the right direction. Thanks!

Basicaly You are right.

You have class IncidentReportFactory with metohd CreateConcreteReport which created the ConcreteReport object depends of reportType

Inheriting from abstract class is I my opinion is not nessesery. Your ReportFactory abstract class have no methods so is not need to use it. It is low abstract when is not methods witch can by shared. It is good to have interface do this.

public interface IIncidentReportFactory
{
 public IConcreteReport CreateConcreteReport();
}

And the implementation:

public class IncidentReportFactory : IIncidentReportFactory
{
    public IncidentFactory(List<Incident> incidents, string reportType)
    {
        //Initialize properties
    }

    public ConcreteReport CreateConcreteReport()
    {
        switch(this.ReportType)
        {
            case "ByLocation": return new IncidentLocationReport(incidents);
                               break;
            case "ByType": return new IncidentTypeReport(incidents);
                           break;
        }

      return null //no match
    }

Also You must change some name:

var reportFactory = new IncidentReportFactory(incidents, "ByLocation");

reportFactory is very misunderstanding name. Is not a reportFactory is a ConcreteReport object.

When You change abstract class to interface then ReportsGenerator class shoud by like this

//Report generator class
public ReportsGenerator{
     public ReportsGenerator(IConcreteReport concreteReport){
           this.concreteReport= concreteReport;
     }

     public PDFView GetPdfView(){

          var pdfView = ConstructPdfWithAllFormatting(this.concreteReport);
          return pdfView;
     }
}

Also is a good practise to use Dependency Injection Container

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