2016-03-09 1 views
2

Я хочу отделить этот проект Qt Calculator Example от модуля GUI и модуля Business Logic. Каков наилучший способ сделать это, и лучше ли писать логический модуль только на C++, чтобы я мог использовать его и в других IDE?Модули Qt GUI и Business Logic

+0

Шаблон MVC в сочетании с правилом, согласно которому модель не должна использовать типы Qt, приведет вас в правильном направлении. –

ответ

1

Лучшая практика или дизайн в вашем случае GRASP Controller модель.

В вашем случае - это означает, что вы должны полностью отделить класс Calculator от материалов Qt (например, QWidget).

Итак - если вам нужно что-то представить от Calculator к виджетам Qt - создайте и используйте интерфейс, например CalculatorPresentationInterface.

Чтобы получить некоторые обратные вызовы, события GUI для калькулятора - сделать слоты обратных вызовов или интерфейс CalculatorConrollerInterface.

Итак, ваш калькулятор будет реализовывать CalculatorConrollerInterface, чтобы иметь возможность получать события из графического интерфейса.

Используйте dependency injection pattern, чтобы ввести Calculator через CalculatorConrollerInterface в ваш GUI.

Ваш GUI должен реализовать (или вы можете использовать adapter pattern) CalculatorPresentationInterface и вы должны вводить свой графический интерфейс для вашего реального Calculator класса через CalculatorPresentationInterface.

Таким образом, оба слоя уровня бизнес-логики (калькулятор) и логики представления (Qt GUI) будут отделены друг от друга, и вы можете легко обменивать оба слоя.


Пример (каждый класс в отдельном файле).

Интерфейсы:

class CalculatorConrollerInterface 
{ 
public: 
    virtual void onAdd() = 0; 
    virtual void onCurrentNumberChange(int number) = 0; 
}; 
class CalculatorPresentationInterface 
{ 
public: 
    virtual void showResult(int result) = 0; 
}; 

Калькулятор - не должен иметь никакого отношения к Qt:

class Calculator : public CalculatorConrollerInterface 
{ 
public: 
     Calculator(CalculatorPresentationInterface& presentation) 
     : presentation(presentation) 
     {} 
    virtual void onAdd() override 
    { 
     // no idea this is correct - just example 
     previousNumber = previousNumber + currentNumber; 
     currentNumber = 0; 
     presentation.showResult(previousNumber); 
    } 

    void onCurrentNumberChange(int number) override 
    { 
      currentNumber = number; 
    } 
private: 
     CalculatorPresentationInterface& presentation; 
     // all stuff necessary to calculate 
     int previousNumber; 
     int currentNumber; 
}; 

Qt презентацию для калькулятора:

class QtCalculatorPresentation : public CalculatorPresentationInterface 
{ 
public: 
    void setController(CalculatorConrollerInterface& controller) 
    { 
     this->controller = &controller; 
    } 
    void showResult(int result) override; 

private: 
    CalculatorConrollerInterface* controller; 
    // plus all Qt widgets necessary 
    // and they shall forward any event to controller 
}; 

И ваш главный:

#include "Calculator.hpp" 
#include "QtCalculatorPresentation .hpp" 

int main() 
{ 
     // dependency injections 
     QtCalculatorPresentation qtPresentation; 
     Calculator calculator(qtPresentation); 
     qtPresentation.setController(calculator); 

     qtPresentation.exec(); 
} 
+0

Учитывая, что Qt представляет собой платформу разработки приложений, одержимость сохранением бизнес-логики, не использующей Qt, является IMHO необоснованной. Вы теряете сигналы/слоты, интроспекцию, потоки, сообщения (события) и т. Д. Для бизнес-объекта калькулятора вы действительно должны использовать конечный автомат, например QStateMachine, поскольку эти вещи * заведомо * трудно получить правильный код, а пример кода с неправильной функциональностью почти вездесущий в Интернете именно потому, что люди не утруждают себя указателем состояния для системы. –

+0

С Qt вам не нужна смирительная рубашка фиксированного класса интерфейса с виртуальными методами, определяющими интерфейс. Очень просто подключить гетерогенных клиентов и поставщиков, использующих сигналы/слоты; функторы могут использоваться для адаптации несоответствующего поставщика к потребностям клиента и т. д. Насколько мне известно, классический шаблон «интерфейс как абстрактный класс» очень негибкий и очень сложный в использовании (или отсутствует!) при взаимодействии с сторонним кодом.Обычно интерфейсы не задаются как абстрактные классы, а конкретные классы только с одной реализацией, определяющей API. –

+0

@KubaOber - 1) В C++ 14 + boost у вас есть все, что вы можете себе представить, Qt когда-либо обеспечит. 2) Если вам действительно нужны таймеры qt state-machine/qt и т. Д. - тогда точно так же вы можете создать его в Qt - и подключиться через интерфейс C++ к вашему «бизнес-контроллеру» - чтобы он мог использовать абстрактные таймеры и т. Д. ... – PiotrNycz

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

  • Нет связанных вопросов^_^