zurück zum Artikel

Patterns in der Softwareentwicklung: Die Template-Methode

Rainer Grimm
Stiliisierte Atomstruktur

(Bild: Iaroslav Neliubov/Shutterstock.com)

Die Schablonenmethode definiert ein Skelett eines Algorithmus und delegiert einzelne Schritte des Algorithmus an Unterklassen.

Patterns sind eine wichtige Abstraktion in der modernen Softwareentwicklung. Sie bieten eine klar definierte Terminologie, eine saubere Dokumentation und das Lernen von den Besten. Die Schablonenmethode ist wohl eines der am häufigsten verwendeten Entwurfsmuster aus dem Buch "Design Patterns: Elements of Reusable Object-Oriented Software [1]".

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++.

Die Grundidee der Schablonenmethode ist einfach zu verstehen. Sie definiert das Skelett eines Algorithmus, der aus einigen typischen Schritten besteht. Implementierungsklassen können nur die Schritte anpassen, aber das Skelett nicht verändern. Die Schritte werden gerne als Hook-Methoden bezeichnet.

Zweck

Anwendungsfall

Struktur

AbstractClass

ConcreteClass

// templateMethod.cpp

#include <iostream>

class Sort{
public:
    virtual void processData() final { // (4)
        readData();             
        sortData();
        writeData();
    }
    virtual ~Sort() = default;
private:
    virtual void readData(){}        // (1)  
    virtual void sortData()= 0;      // (2)
    virtual void writeData(){}       // (3)
};


class QuickSort: public Sort{
    void readData() override {
        std::cout << "readData" << '\n';
    }
    void sortData() override {
        std::cout <<  "sortData" << '\n';
    }
    void writeData() override {
        std::cout << "writeData" << '\n';
    }
};

class BubbleSort: public Sort{
    void sortData() override {
        std::cout <<  "sortData" << '\n';
    }
};


int main(){

    std::cout << '\n';

    QuickSort quick;
    Sort* sort = &quick;          // (5)
    sort->processData();

    std::cout << "\n\n";

    BubbleSort bubble;
    sort = &bubble;               // (6)
    sort->processData();

    std::cout << '\n';
  
}

Das Sortieren besteht aus drei Schritten: readData (1), sortData (2) und writeData (3). Die Mitgliedsfunktionen readData und writeData bieten eine Standardimplementierung an, aber die Mitgliedsfunktion sortData() ist rein virtuell. Diese drei Schritte sind das Grundgerüst des Algorithmus processData (4). Jetzt können Quicksort (5) und Bubble Sort (6) angewendet werden.

Hier ist die Ausgabe des Programms:

Ich habe die Skelettfunktion processData und ihre drei Schritte als virtuelle Funktion implementiert. Dank der drei virtuellen Mitgliedsfunktionen tritt die späte Bindung ein und die Mitgliedsfunktionen des Laufzeitobjekts werden aufgerufen. Die Skelettfunktion als virtuell und final zu deklarieren, ist in C++ hingegen ein Overkill. final bedeutet, dass eine virtuelle Funktion nicht überschrieben werden kann.

Wenn eine Mitgliedsfunktion nicht überschreibbar sein soll, mache sie nichtvirtuell.

Non-Virtual Interface (NVI) Idiom

Die idiomatische Art, die Schablonenmethode in C++ zu implementieren, ist über ein NVI-Idiom. Non-Virtual Interface bedeutet, dass das Skelett nicht virtuell ist und die Schritte virtuell sind. Da der Client die Schnittstelle verwendet, kann das Skelett nicht geändert werden. Hier ist die entsprechende Implementierung der Schnittstelle Sort:

class Sort{
 public:
    void processData() {
        readData();
        sortData();
        writeData();
    }
    virtual ~Sort() = default;
private:
    virtual void readData(){}
    virtual void sortData()= 0;
    virtual void writeData(){}
};

Herb Sutter machte NVI im Jahr 2001 in C++ populär. In seinem Artikel Virtuality [2]reduziert er das NVI-Idiom auf vier Richtlinien:

Vorteile

Nachteile

Nur ein Muster aus dem Buch "Design Patterns: Elements of Reusable Object-Oriented Software [6]" fehlt auf meiner Reise noch: das Strategiemuster. Es wird häufig in der Standard Template Library verwendet. Ich werde in meinem nächsten Artikel auf das Strategiemuster eingehen. ( [7])


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

Links in diesem Artikel:
[1] https://en.wikipedia.org/wiki/Design_Patterns
[2] http://www.gotw.ca/publications/mill18.htm
[3] https://en.wikipedia.org/wiki/Strategy_pattern
[4] https://wiki.c2.com/?HollywoodPrinciple
[5] https://en.wikipedia.org/wiki/Factory_method_pattern
[6] https://en.wikipedia.org/wiki/Design_Patterns
[7] mailto:rainer@grimm-jaud.de