Factory pattern


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 8 of 8

Thread: Factory pattern

  1. #1
    Join Date
    May 2004
    Posts
    242

    Factory pattern

    Hello everyone,

    I have a some code which does the factory pattern :-

    int RealTimeReports::run(int argc, char** argv)
    {
    m_configFile = ...// this is not relevant to the factory pattern
    if ( PluginTranslator::factory().make( msg ) )
    {
    ...
    }
    }


    The factory pattern code is :-

    PluginTranslator* PluginTranslator::make( const RWCString& msg ) const
    {
    PluginTranslator *product = NULL;
    RWOrderedIterator nextExemplar( *m_list );

    // walk the list looking for an exemplar that likes our string
    while ( PluginTranslator *candidate = static_cast<PluginTranslator*>( nextExemplar() ) )
    {
    if ( candidate != &m_exemplar ) // avoid recursion
    {
    if ( ( product = candidate->make( msg ) ) )
    {
    m_interestedExemplars->insert( product ); // we have found an interested exemplar so add it to our list
    }
    }
    }

    return product;
    }



    Each one of the 'make' does something like :-

    PluginTranslator* FinancedPositionTrades::make( const RWCString& msg ) const
    {
    PluginTranslator* product = NULL;

    product = new FinancedPositionTrades( msg );

    return product;
    }

    or :-

    PluginTranslator* WeightedAverageTrades::make( const RWCString& msg ) const
    {
    PluginTranslator* product = NULL;

    product = new WeightedAverageTrades( msg );

    return product;
    }

    etc.



    Each one of the 'makes' calls another 'new', for example :-

    FinancedPositionTrades::FinancedPositionTrades( const RWCString& msg )
    : PluginTranslator( msg )
    {

    Trades = new FinancedPosition( msg );
    }


    WeightedAverageTrades::WeightedAverageTrades( const RWCString& msg )
    : PluginTranslator( msg )
    {

    Trades = new WeightedAverage( msg );
    }

    In these methods just before doing the 'new FinancedPosition ( msg )' or 'new WeightedAverage( msg )' I need to access the m_configFile of class RealTimeReports mentioned right at the beginning.

    I've been trying to create a pointer to RealTimeReports and then access getConfigFile() method but this didn't work.

    I should mention that if I can just set m_configFile for PluginTranslator from RealTimeReports then this will do the trick - however, I'm not sure how to access RealTimeReports from PluginTranslator at the moment (the hierarchy does not allow it). FYI: later on after all the 'makes' have completed, back in the 'main' program, we're doing :-

    RWOrderedIterator nextReport( *PluginTranslator::Exemplars() );

    while ( PluginTranslator *candidate = static_cast<PluginTranslator*>( nextReport() ) )
    {
    candidate->setConfigfile( *m_configFile );
    candidate->createFiles();
    }

    But as you can see this is too late for me. I need to setConfigfile as part of the 'makes'.

    The main issue I have is that I'm not in a poisition to change the main program, nor the factory pattern code. I can only change from the next point of 'make' and what happens after it, i.e. only from here :-

    FinancedPositionTrades::FinancedPositionTrades( const RWCString& msg )
    : PluginTranslator( msg )
    {

    Trades = new FinancedPosition( msg );
    }


    I workaround this by setting m_configFile to an extern variable and then I can use the extern'd variable in FinancedPositionTrades::FinancedPositionTrades( const RWCString& msg ).

    But any other nicer solutions ?

    Can someone please help ?

    Many thanks.
    Last edited by ami; 08-30-2009 at 11:15 AM.

  2. #2
    Join Date
    Nov 2003
    Posts
    4,118
    Can you add an extra argument to RealTimeReport::Run? If so, add a reference variable that will contain the value of m_configFile so that the caller of Run() will be able to examine it like this:

    rtreport.Run(argv, argc, var);
    //check var here

    Alternatively, you can derive from RealTime Report another class that has a member function that returns the value of m_configFile and use that class instead of RealTimeReport. A third option: use environment variables. Have RealTimeReport set an environment variable to the value of m_configFile and then access that variable from any other section of the program using getenv(). Please note that getenv() might not be thread-safe (check the documentation of your compiler).
    Danny Kalev

  3. #3
    Join Date
    May 2004
    Posts
    242
    Hi Danny,

    Many thanks for the information.

    I like the second proposed solution best as I cannot change the parameters to run() and also there are a number of values I wish to get from the file, so if I need to use putenv for each, I'll have more than just a few.

    I did so far in class RealTimeReports
    {
    public:
    RealTimeReports(int argc, char** argv);
    ~RealTimeReports();

    ConfigurationFile* getConfigFile(void) { return m_configFile; }
    }


    and as suggested :-

    class Derived_RealTimeReports : public RealTimeReports
    {

    private:
    ConfigurationFile* derived_m_configFile;
    public:
    Derived_RealTimeReports()
    void set_derived_m_configFile(void)
    {
    // get config file from base class RealTimeReports
    derived_m_configFile = getConfigFile();
    }

    ConfigurationFile* get_derived_m_configFile(void)
    {
    return derived_m_configFile;
    }
    friend class FinancedPositionTrades;

    };

    Using Friends I'll be able to access derived_m_configFile which is in fact the same as m_configFile of RealTimeReports.

    In my 'main' I have :-

    Derived_RealTimeReports amiCfg;
    amiCfg.set_derived_m_configFile();

    At the moment, I'm getting compilation error :-

    /hfx/opt/Sun_ONE_Studio_11_Compiler_Collection/SUNWspro/prod/bin/stdlibfilt -stderr </tmp/c++filt.02262.1.err
    Undefined first referenced
    symbol in file
    Derived_RealTimeReports::Derived_RealTimeReports() RealTimeReports.o
    ld: fatal: Symbol referencing errors. No output written to RealTimeReports


    Is there a problem with my constructor of my derived class ?

    I tried with a pointer, but it's not initialising properly and the program crashes. How do I initialise the derived class with the base details of base class (or in fact with only part of it, i.e. m_configFile).

    Secondly, for the Friends part : would I be able to just access get_derived_m_configFile, or do you just need to mention Derived_RealTimeReports::get_derived_m_configFile ?


    Can you help ?

    Many thanks.
    Last edited by ami; 08-30-2009 at 09:32 PM.

  4. #4
    Join Date
    Nov 2003
    Posts
    4,118
    Yes, you need to place a ; after the constructor declaration.

    You made the right choice I believe -- derivation is the proper way in OOP to extend the functionality of an existing class without creating two many dependencies on implementation details and without resorting to hacks.
    Last edited by Danny; 08-31-2009 at 03:42 AM.
    Danny Kalev

  5. #5
    Join Date
    May 2004
    Posts
    242
    Thanks Danny for your assistance.

    I checked my code and I do in fact have ; as follows :-

    class Derived_RealTimeReports : public RealTimeReports
    {

    private:
    ConfigurationFile* derived_m_configFile;
    public:
    Derived_RealTimeReports();
    void set_derived_m_configFile(void)
    {
    derived_m_configFile = getConfigFile();
    // get config file from base class RealTimeReports
    }
    ConfigurationFile* get_derived_m_configFile(void)
    {
    return derived_m_configFile;
    }

    friend class FinancedPositionTrades;
    };


    and then :-


    Derived_RealTimeReports amiCfg;
    amiCfg.set_derived_m_configFile();

    Can you please advise why I'm still getting this compilation or possible linking error :-


    /hfx/opt/Sun_ONE_Studio_11_Compiler_Collection/SUNWspro/prod/bin/stdlibfilt -stderr </tmp/c++filt.27294.1.err
    Undefined first referenced
    symbol in file
    Derived_RealTimeReports::Derived_RealTimeReports() RealTimeReports.o
    ld: fatal: Symbol referencing errors. No output written to RealTimeReports

    Any ideas what this error means ?

    I added to my c'tor Derived_RealTimeReports(int argc, char** argv) : RealTimeReports(argc, argv) { } but this causes other issues as the base class c'tor is getting invoked again and this causes other issues - no failures, but the log file says : " _pApp != NULL - are you trying to embed one standard console app inside another?".

    Also, I cannot add another no arguments c'tor to RealTimeReports due to :-

    RealTimeReports::RealTimeReports(int argc, char** argv)
    : TradeEventOutput("RealTimeReports", TRUE)
    {

    m_sleepSeconds = 300;

    enableService(versionNo, argc, argv);
    }


    Is there any way to derive from a base class and without having to call the base class c'tor ? If so, how will I still just make sure that I'm pointing to the RealTimeReport object created ?

    In short please see the following example that shows my problem :-

    #include <iostream>
    using namespace std;

    // base and derived class declaration part
    class vehicle
    {
    public:

    vehicle(int input_wheels, double input_weight)
    {
    cout<<"It is me!, Constructor #2, own by base class"<<'\n';
    }

    };

    class car : public vehicle
    {
    int passenger_load;
    public:
    car(void) : vehicle(NULL, NULL)
    {
    cout<<"It is me!, Constructor #3, derived class, car"<<'\n';
    }

    car(int people, int input_wheels, double input_weight):vehicle(input_wheels,
    input_weight), passenger_load(people)
    {
    cout<<"It is me!, Constructor #4, derived class, car"<<'\n';
    }
    };

    // main program
    int main()
    {
    car a;
    return 0;
    }

    This produces :

    It is me!, Constructor #2, own by base class
    It is me!, Constructor #3, derived class, car


    Is there any way to only call the c'tor on the derived class without calling the base class. I know I can use singleton for the base class, but I cannot change its definition as it stands.

    Does this make sense ?



    Many thanks.
    Last edited by ami; 08-31-2009 at 05:13 PM.

  6. #6
    Join Date
    Nov 2003
    Posts
    4,118
    Your derive class ctor must pass the arguments to the base class's ctor of the latter takes arguments:

    Code:
    Derived_RealTimeReports()::RealTimeReports(argc, argv) {/*define your ctor here*/}
    Last edited by Danny; 08-31-2009 at 09:25 PM.
    Danny Kalev

  7. #7
    Join Date
    May 2004
    Posts
    242
    Hi Danny,

    Thanks for that.

    Excatly!! This is exactly what I've been trying but since my base class starts another instance of RealTimeReports (which is a process that runs in the background), I'm getting in the log file an error saying: are you starting a process within another ? - initially, main creates a process running in the background and then when I go to the derived class, it will create another one. Is there a way from preventing this to happen ?

    My RealTimeReports c'tor is :-

    RealTimeReports::RealTimeReports(int argc, char** argv)
    : TradeEventOutput("RealTimeReports", TRUE)
    {

    m_sleepSeconds = 300;

    enableService(versionNo, argc, argv);
    }

    The enableService is a third party API causing a loop in the background waiting for changes in the database.

    So in other words, I want to invoke the Derived class c'tor without invoking the base class c'tor.

    On the other hand, I cannot add another c'tor to the Base class which doesn't do anything because as you can see this inherits from TradeEventOutput which is third party's :-

    RealTimeReports::RealTimeReports(int argc, char** argv)
    : TradeEventOutput("RealTimeReports", TRUE)
    {
    ...
    }



    Does this make sense ?

    Many thanks.
    Last edited by ami; 09-01-2009 at 02:23 AM.

  8. #8
    Join Date
    Nov 2003
    Posts
    4,118
    The problem is that each ctor (the base's and the derived's) launch a new process. That's a problematic design. You need to remove the process launching from the ctor into a separate member function that will be called explicitly, say Run().
    If you can't modify the base class, remove the process launching call from the derived's ctor and pass all the necessary arguments to the base class ctor so that it will be the only ctor launching a new process. As a rule, a ctor shouldn't launch processes, threads or do something that's not proper initialization of its object because a ctor call isn't optional, unlike other user-declared member functions.
    Danny Kalev

Similar Threads

  1. Initialize data after Factory Pattern
    By julen in forum .NET
    Replies: 0
    Last Post: 04-29-2009, 01:48 PM
  2. Correct Design Pattern for Order Form
    By Need2CSharp in forum Architecture and Design
    Replies: 1
    Last Post: 07-28-2007, 08:50 AM
  3. Java Singleton Pattern Tutorial
    By hemanthjava in forum Java
    Replies: 2
    Last Post: 11-14-2006, 10:57 PM
  4. how to list resources in a package?
    By stoughto in forum Java
    Replies: 2
    Last Post: 06-11-2006, 09:56 AM
  5. Replies: 5
    Last Post: 01-17-2002, 08:24 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center