none
Factory pattern question RRS feed

  • Question

  • i am building a data access layer for some reports. this is a smart client application so the report data may be generated from a database or from a locally stored xml file, etc. i dont want my business layer to worry about how the data is retrieved. all my business layer should say is "get me the data! i don't care how! just get me it!".

    i thought that i could use a factory pattern - something like this:

    ReportFactory reportFactory = new ReportFactory();

    IReport myReport = reportFactory.GetReport(StorageTypes.Database);

    DataTable dataTable = myReport.GetData();

    ok. but in this scenario the database driven class needs some extra settings such as connection string. whereas the xml based report might need to know other stuff such as file path etc. so in this case using a factory pattern becomes complicated, as although the classes share common methods, they also require different fields.

    how do i overcome this? delegates? inherited interfaces?

    thanks

    Tuesday, January 16, 2007 1:47 AM

Answers

  • I agree with Huseyin's recommendation to go for an BaseReportProvider. I would prefer it renamed to "ReportProviderBase". If i am not wrong, this is an "Abstract Factory" pattern. I guess Huseyin advice would result in something like this...

    abstract class ReportProviderBase {
      public virtual Initialize (NameValueCollection config) {
         ... setup basic config values required by all providers ...
      }

      public abstract (DataSet or whatever) GetReport (... report arguments ...);
    }

    public class XMLReportProvider : ReportProviderBase {
      public override Initialize (NameValueCollection config) {
        base.Initialize (config);
        file_path = config["FilePath"];
        if (null == file_path || file_path.Trim().Length == 0) {
          throw new ProviderException ("Missing or empty attribute 'FilePath'.");
        }

      }

      public override (DataSet or whatever) GetReport(... report arguments ...) {
        ... do stuff ...
      }
    }

    public class DatabaseReportProvider : ReportProviderBase {
      public override Initialize (NameValueCollection config) {
        base.Initialize (config);
        conn_string = config["ConnectionString"];
        if (null == conn_string || conn_string.Trim().Length == 0) {
          throw new ProviderException ("Missing or empty attribute 'ConnectionString'.");
        }

      }

      public override (DataSet or whatever) GetReport(... report arguments ...) {
        ... do stuff ...
      }
    }


    - Badri

     

    Wednesday, January 17, 2007 4:59 AM

All replies

  • Wee,

    I think you are using a pattern in which we have a single factory class to create the object and have one helper class(haing all the database interacting fucntions like createcommand ,executereader) per database.

    This is a good pattern if the number of tables and database fucntions required are less.

    More suitable pattern is DAO pattern in which we have generally three classes (entity class, factory class and collections class(if needed)) for each tables. In this we restrict the columns of a table inside one entity in DAL created.Things like connection string can also be centralised.

    You can easily create a DAL for a given database automatically using various tools available  like Codus etc.

    Hope i am able to answer to your query

    regards 

    Note:In case i am able to resolve your query, please  mark it as answer

    Tuesday, January 16, 2007 7:12 AM
  • hi .

    you can use enterprise library for this problem.

    it's already designed

    thanks

    Tuesday, January 16, 2007 12:04 PM
  • You should create an abstract class (BaseReportProvider)  and inherit classes from that class named XMLReportProvider or DatabaseReportProvider.
    BaseReportProvider class should has a GetReport method and inherited classes must implement this method.

    Tuesday, January 16, 2007 1:38 PM
  • I agree with Huseyin's recommendation to go for an BaseReportProvider. I would prefer it renamed to "ReportProviderBase". If i am not wrong, this is an "Abstract Factory" pattern. I guess Huseyin advice would result in something like this...

    abstract class ReportProviderBase {
      public virtual Initialize (NameValueCollection config) {
         ... setup basic config values required by all providers ...
      }

      public abstract (DataSet or whatever) GetReport (... report arguments ...);
    }

    public class XMLReportProvider : ReportProviderBase {
      public override Initialize (NameValueCollection config) {
        base.Initialize (config);
        file_path = config["FilePath"];
        if (null == file_path || file_path.Trim().Length == 0) {
          throw new ProviderException ("Missing or empty attribute 'FilePath'.");
        }

      }

      public override (DataSet or whatever) GetReport(... report arguments ...) {
        ... do stuff ...
      }
    }

    public class DatabaseReportProvider : ReportProviderBase {
      public override Initialize (NameValueCollection config) {
        base.Initialize (config);
        conn_string = config["ConnectionString"];
        if (null == conn_string || conn_string.Trim().Length == 0) {
          throw new ProviderException ("Missing or empty attribute 'ConnectionString'.");
        }

      }

      public override (DataSet or whatever) GetReport(... report arguments ...) {
        ... do stuff ...
      }
    }


    - Badri

     

    Wednesday, January 17, 2007 4:59 AM
  • thanks that makes a lot of sense to me
    Wednesday, January 17, 2007 5:25 AM