Mixing Command pattern, Factory pattern and templates all together …

删除回忆录丶 提交于 2019-12-12 10:19:46

问题


I already asked a similar question here, however I didn't really get the answer I wanted because my question was poorly formulated and the examples were bad. So I give it another shot, with hopefully a better explanation and better code .

The code bellow has been stripped out of unnecessary details but it works . The thing is I would like to use Template Argument Deduction, if possible, to simplify the templated function call .

I have a factory which creates commands. To create a command, I use a call like that one :

mCommandFactory.createCommand<
                        DoSomeStuff, 
                        ParameterType1, 
                        ParameterType2, 
                        ParameterType3, 
                        ParameterType4
                        >
                        (std:string("some description"), 
                         parameter1, 
                         parameter2, 
                         parameter3, 
                         parameter4);

As you probably have guessed, parameter1 type is ParameterType1, and so on ... .

Now if we look at the definition of the command - DoSomeStuff- itself :

class DoSomeStuff : public UndoableCommand< ParameterType1 , ParameterType2, ParameterType3 , ParameterType4 >
    {
    public:
      DoSomeStuff(... /* arguments which are needed for precessing the command and undoing it*/ );
      ~DoSomeStuff() throw();
      void executeImpl();
      void undoImpl();

    protected:
              ... /* members which are needed for precessing the command and undoing it*/ 
    };

As you can see, ParameterTypeN information is already inside DoSomeStuff declaration.

I was wondering if it was possible somehow to replace the createCommand call above by something simpler :

mCommandFactory.createCommand<DoSomeStuff>
                        (std:string("some description"), 
                         parameter1, 
                         parameter2, 
                         parameter3, 
                         parameter4);

Here is the CommandFactory code :

    class CommandFactory
    {
    private:
          // some stuff used to initialize objects created by this factory 

    public:
        CommandFactory(...) : ... /* members initialization */

        {  
        }


        template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
        void createCommand(juce::String& description,P1 p1, P2 p2, P3 p3, P4 p4)
        {
            Undoable* cmdPtr = new CommandType(p1, p2, p3, p4);
            ...
            // init cmdPtr

            (*cmdPtr)();            
        }

Basically the point would be to move the complexity inside CommandFactory, to keep the "client code" (the call to createCommand) as simple and short as possible.

Any ideas ?


回答1:


Not sure I understand the question correctly, but this should work.

template<typename ParameterType1 , typename ParameterType2, typename ParameterType3 , typename ParameterType4>
class UndoableCommand
{
public:
    UndoableCommand(ParameterType1 p1, ParameterType2 p2, ParameterType3 p3, ParameterType4 p4)
    {}
};

class DoSomeStuff : public UndoableCommand< int ,double, std::string , int>
{
public:
    DoSomeStuff(int p1, double p2, std::string p3, int p4)
        :UndoableCommand(p1,p2,p3,p4)
    {}
};

class CommandFactory
{
public:
    CommandFactory()
    {}

    template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
    void createCommand( std::string& description,P1 p1, P2 p2, P3 p3, P4 p4)
    {
        UndoableCommand<P1,P2,P3,P4> * cmdPtr = new CommandType(p1, p2, p3, p4);

    }
 };

Used as such

CommandFactory fact;
fact.createCommand<DoSomeStuff>(std::string("description"),1,2.0,std::string("3"),4);



回答2:


You don't need something special here, your approach mCommandFactory.createCommand<DoSomeStuff>(...); shall work. Compiler will automatically deduct types of given arguments from function call expression and instantiate createCommand<> template correctly.




回答3:


Yes you can replace it with something simpler. Have you considered std::bind?

Once you use change it to use <function>, your DoSomeStuff class will just be a struct that holds a pair of std::functions.




回答4:


You can make typedefs of Parameter types to Commandtype class, and thus resolve the parameter types inside createCommand function without explicitly addign them as template parameters. To make that happen, you could make typedefs of template parameters passed to UndoableCommand inside that class.



来源:https://stackoverflow.com/questions/11972818/mixing-command-pattern-factory-pattern-and-templates-all-together

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!