dimanche 18 février 2018

Design pattern alternative for factories : classes with different constructors

I am writing an application that can launch new process'. I have identified that these process' will fundamentally differ in two ways, either they can run standalone or depend on an existing process to function. So I therefore have created two abstract classes, inheriting from a base abstract class.

I am trying to work out how to write a factory or other design pattern that will return the class I need depending on a file extension string I give, which will happen at runtime. However I don't think that the factory pattern is a good,sensible fit as these fundamental difference results in differing constructors. I could write myself a huge switch or nested if statement that would work, but for this project I am really trying to increase my c++ knowledge (this is the first time I have used inheritance really).

Say I have my abstract base class :

class launchable {
protected:
    std::string              name;
    std::string              directory;
    std::string              path;
    std::string              fileType;
    std::vector<std::string> launchArgs;
    bool                     hasLaunched;
    launchable(std::string _name, std::string _directory,std::string _fileType,std::vector<std::string> _args);
public:
    virtual void             start() = 0;
    virtual void             stop()  = 0;
    virtual void             writeMessage(std::string theMessage) = 0;
    virtual boost::optional<std::string> readMessage()            = 0;
};

and then two further abstract classes inheriting from this, firstly a standalone class that starts/stops and writes to its own process:

class standalone : public launchable{
protected:
    processManager *manager;
    std::shared_ptr<processManager::launchableProcess> process;
    virtual std::string formatWriteMessage(std::string theMessage) = 0;
    standalone(std::string _name, std::string _directory,std::string _fileType,std::vector<std::string> _args,processManager *_manager);
public:
    virtual void start() = 0;
    virtual void stop()  = 0;
    void writeMessage(std::string theMessage);
    boost::optional<std::string> readMessage();
};

and a dependent class that must start/stop/read/write through a standalone process:

class dependent : public launchable{
protected:
    standalone *dependency;
    dependent(std::string _name, std::string _directory,std::string _type,std::vector<std::string> _args,standalone *_dependency);
public:
    virtual void start() = 0;
    virtual void stop()  = 0;
    void writeMessage(std::string theMessage);
    boost::optional<std::string> readMessage();
};

An example concrete standalone, *nix executable that runs on a command line:

class executable  : public standalone {
private:
    std::string formatWriteMessage(std::string theMessage);
public:
    using standalone::standalone;
    void start();
    void stop();
};

And example concrete dependable, a supercollider patch that must run through a *nix command line interpreter:

class supercolliderPatch : public dependent {
public:
    using dependent::dependent;
    void start();
    void stop();
};

So ideally what I would want is something like (pseudocode):

launchable *sclang = launchableFactory.create("exec",ARGS); // returns a standalone
launchable *patch = launchableFactory.create("supercolliderPatch",sclang,ARGS) // returns a dependable, with dependency set to sclang

And these launchable *instance would be stored within a std::vector.

Essentially my question is: am I on a fools errand trying to lump these two concepts of standalone/dependent into one or can the factory pattern work for me?

Aucun commentaire:

Enregistrer un commentaire