说我有两个主要的类,ApplicationApplicationGUIApplication做很多事情,可以在不知道ApplicationGUI存在的情况下愉快地运行。 ApplicationGUI通过许多方式链接到Application,它可能具有50或100个不同的旋钮,可以改变Application的行为。
ApplicationGUI是一个分层结构,因此它具有许多ControlGroup实例,每个实例包含任意数量的ButtonKnob,甚至包含另一个ControlGroup

当前设计:实例化ApplicationGUI(Application已经使用一组默认参数运行)后,我将Application参数的指针传递给GUI的各个组件。例如:

 my_gui.sound_controlgroup.knob.link_to_param(&(my_application.volume));

如果我需要做一些更复杂的事情,说调用Applicationmy_application.update_something()的成员函数,这是怎么做的?

简单的答案是将指向my_application的指针传递给my_gui.sound_controlgroup.knob,但是如果我只需要调用my_application的功能之一,就好像我在给我的旋钮一个选项来更改它甚至应该了解的所有内容(my_application.update_something_unrelated() , 例如)。在这种情况下,最干净的方法是什么?

另外,这要么要求公开ApplicationGUI的所有子组件,要么要求在层次结构的每个阶段都具有一个功能,以将该指针转发到底层。这导致了很多功能。这是带有大量旋钮的UI的必然结果吗?

最佳答案

快速简短答案

为了实现您的非GUI相关的Application对象和GUIApplication对象之间的交互,我建议应用“属性,方法和事件处理程序”范例。

扩展复杂答案

G.U.I.开发是O.O.P.最实用的实现之一理论。

什么是“属性,方法和事件处理程序”范例?

这意味着非GUI类和GUI类的构建都应具有:

  • 属性
  • 方法
  • 事件处理程序

  • “事件”(处理程序)也称为“信号”,并通过函数指针实现。不确定,但是,我认为您的“旋钮”就像事件处理程序。

    这是一种应用my_application.update_something_unrelated()的技术,您可以在问题中使用它。

    由于C++与Java一样没有属性语法,因此可以使用“getter”和“setter”方法,也可以使用“属性”模板。

    例如,如果您的应用程序具有Close方法,则可以声明类似以下示例的内容。

    注意:它们不是完整的程序,只是一个想法:
    // Applications.hpp
    
    public class BaseApplicationClass
    {
      // ...
    };
    
    public class BaseApplicationClientClass
    {
      // ...
    };
    
    typedef
      void (BaseApplicationClientClass::*CloseFunctor)
        (BaseApplicationClass App);
    
    public class ApplicationClass: public BaseApplicationClass
    {
      // ...
    
      public:
        Vector<BaseApplicationClientClass::CloseFunctor>
          BeforeCloseEventHandlers;
        Vector<BaseApplicationClientClass::CloseFunctor>
          AfterCloseEventHandlers;
    
      protected:
        void ConfirmedClose();
    
      public:
    
        virtual void Close();
    } Application;
    
    // Applications.cpp
    
    void ApplicationClass::ConfirmedClose()
    {
       // do close app. without releasing from memory yet.
    } // void ApplicationClass::ConfirmedClose()
    
    void ApplicationClass::Close()
    {
       // Execute all handlers in "BeforeCloseEventaHandlers"
    
       this.ConfirmedClose();
    
       // Execute all handlers in "AfterCloseEventaHandlers"
    } // void ApplicationClass::Close()
    
    // AppShells.cpp
    
    public class AppShell: public BaseApplicationClientClass
    {
      // ...
    };
    
    void AppShell::CloseHandler(ApplicationClass App)
    {
      // close GUI
    } // void AppShell.CloseHandler(ApplicationClass App)
    
    void AppShell::setApp(ApplicationClass App)
    {
      App->BeforeCloseEventHandlers->add(&this.CloseHandler);
    } // void AppShell.setApp(ApplicationClass App)
    
    void main (...)
    {
       ApplicationClass* AppKernel = new ApplicationClass();
    
       ApplicationGUIClass* AppShell = new ApplicationGUIClass();
    
       AppShell.setApp(App);
    
       // this executes "App->Run();"
       AppShell->Run();
    
       free AppShell();
    
       free AppKernel();
    }
    

    更新:修复了从全局函数指针(也称为“全局函子”)到对象函数指针(也称为“方法函子”)的类型声明。

    干杯。

    关于c++ - 制作GUI时干净的OOP设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29580090/

    10-11 03:06