How to randomly select a class to instantiate without using switch?

前端 未结 2 1060
既然无缘
既然无缘 2020-12-10 14:44

I\'m refactoring a single 3000+-line class with a tangled web of conditionals and switches into a set of worker classes. Previously part of the constructor would select whic

2条回答
  •  抹茶落季
    2020-12-10 15:38

    I would suggest creating a common base class (if you've not already got one) and then using a factory class to encapsulate the creation process. The factory would just return a pointer to your base class which has the prototype run method.

    Something along these lines:

    class Type
    {
        virtual void Run() = 0;
    };
    
    class TypeFoo : public Type
    {
    public:
        TypeFoo() {};
        virtual void Run() {};
        static Type* Create() { return new TypeFoo(); };
    };
    
    class TypeBar : public Type
    {
    public:
        TypeBar() {};
        virtual void Run() {};
        static Type* Create() { return new TypeBar(); };
    };
    
    class TypeBaz : public Type
    {
    public:
        TypeBaz() {};
        virtual void Run() {};
        static Type* Create() { return new TypeBaz(); };
    };
    
    class TypeFactory
    {
        typedef Type* (*CreateFn)();
    
    public:
        static Type* RandomTypeFooWeighted()
        {
            CreateFn create[] = 
            {
                TypeFoo::Create, 
                TypeFoo::Create,   // weighted towards FOO
                TypeBar::Create, 
                TypeBaz::Create
            };   
            const int fncount = sizeof(create)/sizeof(*create);
            return create[ rand()%fncount ]();
        }
    };
    

    So to use it you can just call:

    Type *t = TypeFactory::RandomTypeFooWeighted();
    

    Credit to Nawaz for the function pointer bits and bobs.

提交回复
热议问题