2016-03-12 5 views
3

Я работаю над простой картой, написанной на C++. Теперь у меня есть что-то вродеЛучший способ организовать singleton с виртуальными методами

app.cpp

#include "app.h" 

namespace App 
{ 

} 

void App::init() 
{ 

} 

void App::timerEvent(int time) 
{ 

} 

Но что, если я не хочу слушать TimerEvent в некоторых случаях? Мне все еще приходится писать пустую реализацию метода.

Моя идея заключается в том, чтобы перейти от пространства имен class App : public BaseApp с virtual void BaseApp::init() = 0 и virtual void BaseApp::timerEvent(int time) {} в BaseApp (Similary в Qt QApplication). Однако приложение должно быть одноточечным, но я не вижу способа указать его с BaseApp, поэтому мне нужно написать одноэлементный код в App, и вся виртуальная идея не имеет смысла.

Как его проектировать?

P.S. Я не хочу использовать слушателей здесь. Мне кажется, что это слишком много.

P.P.S. Мне нужен singleton, потому что я инициализирую экземпляр приложения от main, но все же хочу получить доступ к его методам из других классов.

+3

Я не все понимаю, но в любом случае, просто не использовать Singleton и спроектировать архитектуру на основе этого принципа. –

+0

Вы можете * выбрать *, чтобы создать только ** один объект '' App'. Вам не нужен синглтон, чтобы сделать этот выбор. – Galik

+0

@Galik, но я не вижу никакой другой возможности. Я хочу вызвать методы экземпляра приложения из других частей кода. – Ximik

ответ

2

Вы можете эмулировать виртуальные функции внутри вашего пространства имен с помощью указателя на функцию или функции std ::. Просто сделайте примерно так:

#include "app.h" 

namespace App 
{ 
    std::function<void(int)> vtTimerEvent; 
} 

void App::timerEventImpl(int time) 
{ 
    // default timerEvent implementation 
} 

void App::init(std::function<void(int)> timerEvent = &App::timerEventImpl) 
{ 
    vtTimerEvent = timerEvent; 
} 

void App::timerEvent(int time) 
{ 
    vtTimerEvent(time); 
} 

Это не очень хороший дизайн, но он делает то, что вы хотите.

UPDATE

Другое приближение:

#include <memory> 
#include <stdexcept> 

// virtual base interface 
class IInterface 
{ 
public: 
    virtual ~IInterface() = 0; 
}; 

IInterface::~IInterface(){} // must have 

// virtual App interface 
class IApp : 
    virtual public IInterface 
{ 
public: 
    virtual void init() = 0; 
    virtual void timerEvent(int time) = 0; 
}; 


// static App interface 
class App 
{ 
private: 
    ~App(); // nobody can create an instance 
public: 
    static void init(const std::shared_ptr<IApp> &impl_p) 
    { 
     if (!impl) 
     { 
      impl = impl_p; 
      impl->init(); 
     } 
     else 
     { 
      throw std::runtime_error("Already initialized"); 
     } 
    } 

    static void timerEvent(int time) 
    { 
     impl->timerEvent(time); 
    } 
private: 
    static std::shared_ptr<IApp> impl; 
}; 

std::shared_ptr<IApp> App::impl; 

// specific App implementation 
class AppImplementation1 : 
    public IApp 
{ 
    //... 
}; 


int main(int, char**) 
{ 
    auto myImpl = std::make_shared<AppImplementation1>(); 
    App::init(myImpl); 
    //... 
    return 0; 
} 
+0

Спасибо, второй ответ на 100% правильный. – Ximik

Смежные вопросы