模型-视图-控制器(MVC)体系结构

本文主要学习了模型-视图-控制器(MVC)体系结构的基本概念及应用。MVC体系结构是一种用于设计和开发涉及用户交互的应用的经过验证的体系结构。通常用于基于GUI的应用程序以及图形用户界面用户与按钮、菜单等交互。通过举例介绍了mvc模型,学习MVC的运用。
展开查看详情

1.CMPE 135: Object-Oriented Analysis and Design October 2 Class Meeting Department of Computer Engineering San Jose State University Fall 2018 Instructor: Ron Mak www.cs.sjsu.edu/~mak 1

2.Model-View-Controller Architecture (MVC) A proven architecture for the design and development of applications that involve user interaction . Often used for GUI-based applications . Graphical user interface Users interact with buttons, menus, etc. 2

3.Model-View-Controller Architecture , cont’d Design goal: Identify which application objects are model , view , or controller . 3 A user cannot directly modify the model.

4.4 MVC Implementation: Loose Coupling Keep the implementations of the three objects types separate. encapsulation Each type of objects does not depend on how the other types are implemented. loose coupling Your application is easier to develop and maintain faster to develop more flexible (handle changes) more robust (resilient to runtime errors)

5.5 MVC Model Objects Represent the operational data maintained by your application. Can be persisted to files or databases. Examples from the Rock-Paper-Scissors game: player (human and computer) objects score history of choice sequences frequency data

6.6 MVC View Objects View objects represent user interface components . Input components of an application. In each use case, users interact with at least one view object. View objects collect information from users in a form that the model and controller objects can use. RPC game examples: input prompts buttons

7.7 MVC Controller Objects Coordinate the model and view objects. Often have no physical counterpart in the real world. Collect information from view objects for dispatch to model objects. This is how user-entered data can update the model. Represent application control flows . RPC game example: What the program does in response to human and computer choices during each round.

8.Events MVC programs typically process events . Events can be caused by user actions . clicking a button ticking a checkbox or radio button selecting a menu item moving the mouse clicking a mouse button dragging and dropping 8

9.Event Handlers as Callback Functions An event can be processed by an event handler . An event handler is often implemented as a callback function . Has a well-documented signature. Register the function with the GUI framework. Do not call a callback function directly. Instead, it is called by the GUI framework in response to an event. 9

10.Inversion of Control Standard text-based program Your program is in control. Your program determines the application flow. Interactive GUI-based program Your program waits for events to occur. Your program reacts to events when they occur. The GUI framework receives an event and calls the appropriate event handler (callback function). This is inversion of control . The GUI framework determines the application flow. 10

11.wxWidgets We will use wxWidgets , “a C++ library that lets developers create applications for Windows, Mac OS X, Linux and other platforms with a single code base”. See https://www.wxwidgets.org Download from: https://www.wxwidgets.org/downloads/ Online reference: https://docs.wxwidgets.org/3.0/index.html The download includes many sample programs. 11

12.wxWidgets and Eclipse 12

13.wxWidgets and Eclipse , cont’d 13

14.wxWidgets and Eclipse , cont’d 14

15.wx Hello World The application class: 15 #include <iostream> #include < wx / wx.h > using namespace std ; class HelloWorldApp : public wxApp { public:     virtual bool OnInit () wxOVERRIDE ; }; helloworld.cpp

16.wx Hello World , cont’d The application window (frame): 16 class HelloWorldFrame : public wxFrame { public:     HelloWorldFrame ( const wxString & title,                      const wxPoint & pos , const wxSize & size); private:     void OnHello ( wxCommandEvent & event);     void OnBonjour ( wxCommandEvent & event);     void OnGutenTag ( wxCommandEvent & event);     void OnExit ( wxCommandEvent & event);     void OnAbout ( wxCommandEvent & event);     wxDECLARE_EVENT_TABLE (); }; Event handlers Event mapping table helloworld.cpp

17.wx Hello World , cont’d Event codes and the event mapping table. 17 enum {     ID_Hello     = 1,     ID_Bonjour   = 2,     ID_GutenTag = 3 }; wxBEGIN_EVENT_TABLE ( HelloWorldFrame , wxFrame )     EVT_MENU( ID_Hello ,    HelloWorldFrame :: OnHello )     EVT_MENU( ID_Bonjour ,  HelloWorldFrame :: OnBonjour )     EVT_MENU( ID_GutenTag , HelloWorldFrame :: OnGutenTag )     EVT_MENU( wxID_ABOUT ,  HelloWorldFrame :: OnAbout )     EVT_MENU( wxID_EXIT ,   HelloWorldFrame :: OnExit ) wxEND_EVENT_TABLE () Predefined codes helloworld.cpp Event codes Register callback event handlers.

18.wx Hello World , cont’d The macro that will allow wxWidgets to create the application object at run time. 18 wxIMPLEMENT_APP ( HelloWorldApp ); helloworld.cpp

19.wx Hello World , cont’d Event handler for the application’s initialization event. Recall: 19 class HelloWorldApp : public wxApp { public:     virtual bool OnInit () wxOVERRIDE ; }; bool HelloWorldApp :: OnInit () {     cout << " OnInit : Initializing Hello World app!" << endl ;     HelloWorldFrame *frame = new HelloWorldFrame ("Hello World",                                  wxPoint (50, 50), wxSize (450, 340) );     frame->Show(true);     return true; } Success: wxApp :: OnRun () will be called which will enter the main message loop and the application will run. Had we returned false here, the application would exit immediately. helloworld.cpp

20.wx Hello World , cont’d HelloWorldFrame constructor: 20 HelloWorldFrame :: HelloWorldFrame ( const wxString & title,                  const wxPoint & pos , const wxSize & size)     : wxFrame (NULL, wxID_ANY , title, pos , size) {     wxMenu * menuFile = new wxMenu ;     menuFile ->Append( ID_Hello , "&Hello...\ tCtrl -H",                      "Status string: Hello!");     menuFile -> AppendSeparator ();     menuFile ->Append( ID_Bonjour , "&Bonjour...\ tCtrl -B",                      "Status string: Bonjour!");     menuFile ->Append( ID_GutenTag , "& Guten Tag...\ tCtrl -G",                      "Status string     menuFile ->Append( wxID_EXIT , " E&xit ...\ tCtrl -X",                      "Status string: Quit Wx-helloworld "); ... Create the File menu. helloworld.cpp

21.wx Hello World , cont’d HelloWorldFrame constructor , cont’d : 21 ...     wxMenu * menuHelp = new wxMenu ;     menuHelp ->Append( wxID_ABOUT );     wxMenuBar * menuBar = new wxMenuBar ;     menuBar ->Append( menuFile , "&File");     menuBar ->Append( menuHelp , "&Help");     SetMenuBar ( menuBar );     CreateStatusBar ();     SetStatusText ("Welcome to the Hello World app!"); } Create the Help menu. Create the menu bar. Create the status bar. helloworld.cpp

22.wx Hello World , cont’d HelloWorldFrame constructor , cont’d : 21 ...     wxMenu * menuHelp = new wxMenu ;     menuHelp ->Append( wxID_ABOUT );     wxMenuBar * menuBar = new wxMenuBar ;     menuBar ->Append( menuFile , "&File");     menuBar ->Append( menuHelp , "&Help");     SetMenuBar ( menuBar );     CreateStatusBar ();     SetStatusText ("Welcome to the Hello World app!"); } Create the Help menu. Create the menu bar. Create the status bar. helloworld.cpp

23.wx Hello World , cont’d More menu item event handlers: 23 void HelloWorldFrame :: OnHello ( wxCommandEvent & event) {     cout << " OnHello : Hello, world!" << endl ; } void HelloWorldFrame :: OnBonjour ( wxCommandEvent & event) {     cout << " OnBonjour : Bonjour, monde!" << endl ; } void HelloWorldFrame :: OnGutenTag ( wxCommandEvent & event) {     cout << " OnGutenTag : Guten Tag, Welt!" << endl ; } Demo helloworld.cpp

24.#include " ButtonPanel.h " class DemoFrame : public wxFrame { public:     DemoFrame ( const wxString & title);     virtual ~ DemoFrame ();     void on_about ( wxCommandEvent & event);     void on_quit ( wxCommandEvent & event); private:     wxDECLARE_EVENT_TABLE ();     ButtonPanel * button_panel ;     void init ();     void init_menu_bar ();   void init_sizer (); }; wx Buttons Demo: DemoFrame 24 DemoFrame.h

25.#include " ButtonPanel.h " class DemoFrame : public wxFrame { public:     DemoFrame ( const wxString & title);     virtual ~ DemoFrame ();     void on_about ( wxCommandEvent & event);     void on_quit ( wxCommandEvent & event); private:     wxDECLARE_EVENT_TABLE ();     ButtonPanel * button_panel ;     void init ();     void init_menu_bar ();   void init_sizer (); }; wx Buttons Demo: DemoFrame 25 DemoFrame.h

26.#include " DemoFrame.h " wxBEGIN_EVENT_TABLE ( DemoFrame , wxFrame )     EVT_MENU( RPS_Quit ,  DemoFrame :: on_quit )     EVT_MENU( RPS_About , DemoFrame :: on_about ) wxEND_EVENT_TABLE () const int SIDE_MARGINS = 40; DemoFrame :: DemoFrame ( const wxString & title)     : wxFrame (NULL, wxID_ANY , title),       button_panel (new ButtonPanel (this)) {     init ();     wxSize size = GetSize ();     size.SetWidth ( size.GetWidth () + SIDE_MARGINS);     SetSize (size); } DemoFrame ::~ DemoFrame () {     delete button_panel ; } wx Buttons Demo: DemoFrame , cont’d 26 DemoFrame.cpp

27.void DemoFrame :: init () {     init_menu_bar ();     init_panel ();     wxSize size = GetBestSize ();     SetMinClientSize (size); } void DemoFrame :: init_menu_bar () {     wxMenu * fileMenu = new wxMenu ;     fileMenu ->Append( RPS_Quit ,  " E&xit \ tAlt -X", "Quit program");     wxMenu * helpMenu = new wxMenu ;     helpMenu ->Append( RPS_About , "&About F1",   "Show about dialog");     wxMenuBar * menuBar = new wxMenuBar ();     menuBar ->Append( fileMenu , "&File");     menuBar ->Append( helpMenu , "&Help");     SetMenuBar ( menuBar ); } wx Buttons Demo: DemoFrame , cont’d 27 DemoFrame.cpp

28.void DemoFrame :: init_sizer () {     wxSizer * frame_sizer = new wxBoxSizer ( wxVERTICAL );     frame_sizer -> AddSpacer (20);     frame_sizer ->Add( button_panel , 0, wxALIGN_CENTER , 0);     SetSizerAndFit ( frame_sizer ); } wx Buttons Demo: DemoFrame , cont’d 28 Use a wxSizer object to lay out components. Different layouts: wxVERTICAL , wxHORIZONTAL , etc. DemoFrame.cpp

29.wx Buttons Demo: DemoFrame , cont’d 29 void DemoFrame :: on_about ( wxCommandEvent & WXUNUSED(event)) {     wxMessageBox ( wxString ::Format(                     "This is a button demo