【问题标题】:Qt GUI and Business Logic modules [closed]Qt GUI 和业务逻辑模块 [关闭]
【发布时间】:2016-06-23 20:46:21
【问题描述】:

我想把这个项目Qt Calculator Example 分成GUI 模块和业务逻辑模块。最好的方法是什么?最好只用 C++ 编写逻辑模块,这样我也可以在其他 IDE 中使用它?

【问题讨论】:

  • MVC 模式,结合模型不应使用 Qt 类型的规则,将带您走向正确的方向。

标签: c++ qt module calculator


【解决方案1】:

在您的案例中,最佳实践或设计模式是GRASP Controller 模式。

在你的情况下 - 这意味着你应该将 Calculator 类与 Qt 的东西(如 QWidget)完全分开。

所以 - 如果你需要从 Calculator 向 Qt 小部件展示一些东西 - 创建和使用像 CalculatorPresentationInterface 这样的界面。

要获得一些回调、GUI 事件到计算器 - 制作回调槽或接口 CalculatorConrollerInterface

所以 - 您的计算器将实现 CalculatorConrollerInterface 以便能够从 GUI 接收事件。

使用dependency injection pattern 将您的Calculator 通过CalculatorConrollerInterface 注入您的GUI。

你的 GUI 应该实现(或者你可以使用 adapter patternCalculatorPresentationInterface 并且你应该通过 CalculatorPresentationInterface 将你的 GUI 注入到你真正的 Calculator 类中。

通过这种方式,业务逻辑层(计算器)和表示逻辑层(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();
 }

【讨论】:

  • 鉴于 Qt 是一个应用程序开发框架,坚持不使用 Qt 的业务逻辑的痴迷恕我直言是没有根据的。您正在失去信号/槽、内省、线程、消息传递(事件)等...对于计算器业务对象,您确实应该使用状态机,如 QStateMachine,因为这些东西是臭名昭著 很难做到正确,功能错误的示例代码在网络上几乎无处不在,正是因为人们不费心为系统指定状态图。
  • 使用 Qt,您不需要使用指定接口的虚拟方法的固定接口类的紧身衣。使用信号/插槽连接异构客户端和提供者非常容易;函子可用于使不合格的提供者适应客户的需求等。就我而言,经典的“作为抽象类的接口”模式非常不灵活并且很难使用(或不存在! ) 当您与第 3 方代码交互时。通常接口不是作为抽象类给出的,而是只有一个定义 API 的实现的具体类。
  • @KubaOber - 1) 在 C++14+boost 中,您拥有 Qt 所能提供的一切。 2)如果你真的需要一些 qt 状态机/qt 计时器等。 - 那么你可以以同样的方式在 Qt 中创建一个 - 并通过 C++ 接口连接到你的“业务控制器” - 所以它可以使用抽象计时器等...
  • @KubaOber 3) 我总是这样做 - 它很容易使用 - 只是口味问题 - OP 想尝试这种方式 4) 在你的 Qt 世界类中使用信号/插槽 -没问题,甚至是可取的 - 但除此之外 - 只有 C++ 接口才能连接到您的业务逻辑 - 或者使用 std::functionboost::signal...
  • “在 C++14+boost 中,你拥有 Qt 所能提供的一切”不是自省 :)
猜你喜欢
  • 2012-08-26
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
相关资源
最近更新 更多