zurück zum Artikel

Patterns in der Softwarearchitektur: Model-View-Controller

Rainer Grimm

(Bild: Blackboard/Shutterstock.com)

Der Model-View-Controller ist eines der klassischen Architekturmuster für flexible Mensch-Maschine-Schnittstellen.

Patterns sind eine wichtige Abstraktion in der modernen Softwareentwicklung und Softwarearchitektur. Sie bieten eine klar definierte Terminologie, eine saubere Dokumentation und das Lernen von den Besten.Der Model-View-Controller (MVC) ist eines der klassischen Architekturmuster aus dem Buch "Pattern-Oriented Software Architecture, Volume 1 [1]". Es richtet sich an interaktive Anwendungen mit einer flexiblen Mensch-Maschine-Schnittstelle.

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

Das MVC unterteilt die Programmlogik einer Bedienoberfläche in die einzelnen Komponenten Model, View und Controller. Das Model verwaltet die Daten und Regeln der Anwendung. Die View stellt die Daten dar, und der Controller interagiert mit dem Benutzer.

Zweck

Lösung

Struktur

Model

View

Controller

Es gibt zwei interessante Aspekte der MVC: Initialisierung und Benutzereingabe:

Initialisierung

Die folgenden Schritte finden während der Initialisierung des MVC statt:

Benutzereingabe

Bei einem Benutzerereignis finden die folgenden Schritte statt:

Das folgende Programm mvc.cpp wendet MVC an.

// mvc.cpp

#include <iostream>
#include <string>
#include <unordered_map>


class DefectModel {
 public:                                                   // (5)
     mutable std::unordered_map<std::string, std::string>
       defects_ = { {"XYZ" , "File doesn't get deleted."},
                    {"XAB" , "Registry doesn't get created."},
                    {"ABC" , "Wrong title get displayed."} };

    std::string getDefectComponent(const std::string& component) 
      const {
        return defects_[component];
    }

    int getSummary() const {
        return defects_.size();
    }

    std::unordered_map<std::string, std::string> getAllDefects() 
      const {
        return defects_;
    }

};

class DefectView {
 public:
    void showSummary(int num) const {
        std::cout << "There are " + std::to_string(num) + 
          " defects in total!\n";
    }
    
    void showDefectComponent(const std::string& defect) const {
        std::cout << "Defect of component: " + defect + '\n';
    }

    void showDefectList(const std::unordered_map<std::string, 
                        std::string>& defects) const {
        for (const auto& p: defects) {
            std::cout << "(" + p.first + ", " + p.second + ")\n";
        }
    }
};

class DefectController {
    const DefectModel& defectModel;
    const DefectView& defectView;
 public:
    DefectController(const DefectModel& defModel, 
                     const DefectView& defView):
      defectModel{defModel}, defectView{defView} { }

    void showDefectComponent(const std::string& component) 
      const {
        defectView.showDefectComponent(
          defectModel.getDefectComponent(component));    // (6)
    }

    void showDefectSummary() const {
      defectView.showSummary(defectModel.getSummary());  // (7)
    }

    void showDefectList() const {
      defectView.showDefectList(
        defectModel.getAllDefects());                    // (8)
    }

};

int main() {

    std::cout << '\n';

    DefectModel defectModel;
    DefectView defectView;

    
    DefectController defectController(defectModel, 
                                      defectView);  // (1)
    defectController.showDefectComponent("ABC");    // (2)
    std::cout << '\n';
    defectController.showDefectSummary();           // (3)
    std::cout << '\n';
    defectController.showDefectList();              // (4)

    std::cout << '\n';

}

Der Controller holt sich sein Modell und seine Ansicht in seinem Konstruktor (1) und zeigt seine Fehlerliste defects_ (5) auf drei Arten an (2 - 4). Der Controller stößt jeden Aufruf in der main Funktion an und verwendet seine Views, um die vom Modell vorgegebenen Daten anzuzeigen (6 - 8).

Der folgende Screenshot zeigt die Ausgabe des Programms:

Variation

Presentation-Abstraction-Control [2] ist ein weiteres Muster aus dem Buch "Pattern-Oriented Software Architecture, Volume 1 [3] und ähnelt dem MVC. Es verwendet eine hierarchische Struktur von Agenten, wobei jeder Agent aus der Präsentation, der Abstraktion (Modell) und der Datenkontrolle besteht. Die Agenten kommunizieren miteinander mithilfe des Controllers.

Vorteile

Nachteile

Ereignisgesteuerte Anwendungen wie GUIs oder Server verwenden oft das Architekturmuster Reactor. Ein Reactor kann mehrere Anfragen gleichzeitig annehmen und sie auf verschiedene Handler verteilen. (rme [4])


URL dieses Artikels:
https://www.heise.de/-8956787

Links in diesem Artikel:
[1] https://en.wikipedia.org/wiki/Pattern-Oriented_Software_Architecture
[2] https://en.wikipedia.org/wiki/Presentation%E2%80%93abstraction%E2%80%93control
[3] https://en.wikipedia.org/wiki/Pattern-Oriented_Software_Architecture
[4] mailto:rme@ix.de