Friday, 23 January 2015

Factory design pattern in C++ with example

Factory design pattern in C++ with example:

What is the factory pattern?

Let us see overview of the factory pattern:

Factory in real life constructs tangible objects, such as tables, cars and languages.
Like that, a factory in object-oriented programming constructs objects. When you use factories in your program, portions of code that want to create a particular object ask the factory for an instance of the object instead of calling the object constructor themselves.

For example, an interior decorating program might have a CarFactory object.

When part of the code needs a type of car such as a innova, it would call the buyCar() method of the CarFactory object, which would return a new car.

At first glance, factories seem to lead to complicated designs without clear benefits.

It appears that you’re only adding another layer of complexity to the program. Instead of calling buyCar () on a CarFactory, you could simply buy a new car object directly.

However, factories can actually be quite useful. Instead of creating various objects all over the program, you centralize the object creation for a particular domain. This localization is often a better model of real-world creation of objects.


Another benefit of factories is that you can use them alongside class hierarchies to construct objects without knowing their exact class

Below we can see the simple car class:


Simple car class
Your program could drive Cars without knowing whether they were really wagonar or Innova or Swift. but,with standard object-oriented programming, the one place that you’d need to specify wagonar or Innova or Swift is when you create the car. Here, you would need to call the constructor for one or the other.

Let us see the example carFactory model:
Example CarFactory model

The above is the sample overview; Let us see the working example for the factory pattern.

Here in this example we have so many types of files like (.csv, .gpx, .nmea etc), for every type of the file we need to write the ReaderFactory
The ReaderFactory class is
#include "Generalizer.h"
#include "CSVReader.h"
#include "GPXReader.h"
#include "KMLReader.h"
enum Readers
{
  enm_None = 0,
 enm_CSV,
  enm_GPX,
  enm_KML,
  enm_NMEA
};
class Reader_Factory
{
private:
 Generalizer *Reader;
public:
 ~Reader_Factory ()
    { }
 Reader_Factory (const char *input_file, const char *input_filepath, const char *outfilepath, Readers Type) : Reader (NULL)
   { Reader=CreateReaderInstance (input_file,input_filepath,outfilepath,Type); }
 Reader_Factory(const Reader_Factory &) {}
 Reader_Factory &operator=(const Reader_Factory &) {  }
 Generalizer* CreateReaderInstance(const char *input_file, const char *input_filepath, const char *outfilepath, Readers Type)
 {
  Generalizer *Reader = NULL;
  switch (Type)
  {
  case enm_CSV:
    Reader = new CSVReader (input_file, input_filepath, outfilepath);
   break;
  case enm_GPX:
    Reader = new GPXReader (input_file, input_filepath, outfilepath);
   break;
  case enm_KML:
   Reader = new KMLReader (input_file, input_filepath, outfilepath);
   break;
  case enm_NMEA:
   Reader = new NMEAReader (input_file, input_filepath, outfilepath);
   break;
  default:
   break;
  }
  return Reader;
 }
 bool ParseReaderInput()
 {
  bool status = Reader->ParseReaderInput();
  return status;
 }
};

The generalize class is
#include <stdio.h>
#include<iostream>
#include<fstream>
#include<sstream>
#ifndef _GEN_GPS_GENERALIZER_H_
#define _GEN_GPS_GENERALIZER_H_
class Generalizer
{
 Generalizer(){};
 Generalizer( const char* filename, const char* fullpath, const char* Output):                 FrameFileName(filename),FullPathFile(fullpath),OutFile(Output){}
 Generalizer(const Generalizer &){}
      virtual bool ParseReaderInput() { return 0;}
 virtual bool write(Generalizer & ,std::ostream& outstream,char* filename);
 virtual ~Generalizer(){};
};
CSV file parser class
The below is the header file
class CSVReader:public Generalizer
{
public:
 CSVReader(){};
 CSVReader(const char* filename, const char* fullpath, const char* Output): Generalizer(filename, fullpath, Output){}
 CSVReader(const CSVReader &){}
 virtual bool ParseReaderInput();
 virtual ~CSVReader(){};
};
bool CSVReader::ParseReaderInput()
{
  IOFile  *fMovDataFile= new IOFile; [Please give the link to File Operations in C/C++ with examples]
 fMovDataFile->Open(this->FullPathFile,"r");
 char *pcchStr = NULL;
 char** ppchToks = NULL;
 std::filebuf fb;
 fb.open (this->OutFile,std::ios::out);
 std::ostream outstream(&fb);
 int temp_long=0;
 int temp_lat = 0;
 int count =0;
 CSVReader data(this->FrameFileName,this->FullPathFile,this->OutFile);
 CString ocFileNAem (FrameFileName);
 CString ocFilename;//created this cstring ....
 ocFilename = ocFileNAem.Left (ocFileNAem.GetLength () - 3);//created this cstring ....order is important
 ocFileNAem = ocFileNAem.Right(2);//.Left (2);//created this cstring ....
  char framefile[32];
 pcchStr = fMovDataFile->ReadLine ();
 const char *symbol = FindSymbol(pcchStr);
 while (!fMovDataFile->Eof ()) {
  pcchStr = fMovDataFile->ReadLine ();
  if (StrEqual (pcchStr, "") == _TRUE ||
   StrEqual (pcchStr , NULL) == _TRUE)
  { continue; }
  ppchToks = StrTokenizeCmplx (pcchStr, (CChar*)symbol, _FALSE, _FALSE);
  data.date   = ppchToks[1];
  data.time      = ppchToks[2];
  data.latitude       = atof (ppchToks[3]);
  data.longitude      = atof (ppchToks[4]);
  data.altitude  =atof (ppchToks[5]);
  sprintf(framefile,"%s_%d.jpg",ocFilename,count);
  if (ocFileNAem.Compare ("DM") == 0)  {
      int temp_latitude=(int)(data.latitude/100);
      int  temp_long=(int)(data.longitude/100);
  data.latitude= (fmodl( data.latitude, 100.0)/60) +   temp_latitude;
  data.longitude =(fmodl( data.longitude,100.0)/60) + temp_long ;
  }
  data.write((data),outstream,framefile);
  count = count +1;
  Destroy (ppchToks); ppchToks = NULL;
 }
 outstream.clear();
 fb.close();
 fMovDataFile->Close();
 fMovDataFile =NULL;
 return 0;
}

GPX Reader
#include <stdio.h>
#include "Gen_GPSGeneralizer.h"
#endif
class Generalizer;
class GPXReader:public Generalizer
{
public:
 GPXReader(){};
       GPXReader(const char* filename, const char* fullpath, const char* Output): Generalizer (filename,fullpath,Output){}
 GPXReader(const GPXReader &){}
 virtual bool ParseReaderInput();
 virtual ~GPXReader () {};
};
#endif
Similarly, for other formats.
It is also possible to use the factory pattern for more than just modeling real-world factories.

No comments: