Interface-Designs und ihre Implementierungen

Fassade-Pattern

Das Fassade-Pattern bietet dem Zugreifer cController das Interface icCounter an, welches bereits Daten und Funktionsimplementierungen enthält.

Was sich hinter der Fassade icCounter verbirgt, ist für den Zugreifer nicht wissenswert und auch nicht sichtbar.

Anzeige

Wie bei den vorherigen Beispielen enthält diese Implementierung keine virtuellen Funktionen oder Funktionszeiger. Es ergibt sich nur eine Abhängigkeit (Include-Pfad) und damit eine geringe / lose Kopplung. Das Interface (Fassade) enthält ein Zähler- und ein Grenzwert-Prüfobjekt, die gemeinsam die komplette Funktionalität der Fassade realisieren.

 

Interface Designs Bild 10 1000

Anzeige

Bild 10: Fassade-Pattern – Interfacerealisierung

 

Interfaceklasse mit rein virtuellen Funktionen

Ein klassischer, aus der objektorientierten Welt stammender Interfaceansatz ist die Verwendung von rein virtuellen Funktionen (nur Deklarationen ohne Implementierungen) im Interface. Des Weiteren enthält das Interface icCounter keine Daten.

Der Zugriff auf das Interface erfolgt im cController durch einen Zeiger / eine Referenz vom Typ des Interfaces. Dieser Zeiger / diese Referenz muss später auf ein Objekt der Interface-realisierenden Klassen zeigen.

In C gibt es keine virtuellen Funktionen, daher müssen dort die Mechanismen des C++ Compilers manuell mit Hilfe von Funktionszeigertabellen nachgebildet werden.

Was sich hinter dem Interface verbirgt, ist für den Zugreifer cController zunächst nicht wissenswert und auch nicht sichtbar. Erst beim Initialisieren der Zeiger / Referenzen müssen konkrete Objekte von cUpCounter und cDownCounter vorhanden sein.

 

Interface Designs Bild 11 1000

Bild 11: Virtual Interface – Interfacerealisierung

 

Newsletter
Newsletter Box

Mit Klick auf den Button "Jetzt Anmelden" stimme ich der Datenschutzerklärung zu.

Interfaceklasse mit nicht nur rein virtuellen Funktionen

Diese Implementierungsvariante basiert auf dem C++ Idiom Non-Virtual Interface (NVI). Bei der Implementierung von rein virtuellen Interfaces ergeben sich im Falle mehrerer Implementierungen typischerweise redundante Programmcode-Anteile.

Das Idiom Non-Virtual Interface implementiert diesen gemeinsamen Code bereits in der Interface-Funktion. Nur die kleinen varianten Anteile der typspezifischen Implementierung sind im Interface als rein virtuelle Funktionen deklariert (isInRange()) und (count_raw()) und bereits in anderen implementierten Funktionen (count())  aufgerufen.

Nur die beiden typspezifischen virtuellen Funktionen isInRange() und count_raw() sind jeweils in den Klassen cUpCpounter und cDownCounter individuell implementiert.

 

Interface Designs Bild 12 1000

Bild 12: Non-Virtual Interface

 

In den Beispielen mit virtuellen Funktionen in Interfaces oder/und Klassen führt das Ergebnis auf dem Taget zu einer dynamischen Bindung. Dadurch entstehen verschieden Aufwände, die aber im Vergleich zum Nutzen in dem meisten Fällen vernachlässigbar sind:

1. Programmspeicher (und Compilezeit)

Zur Compilezeit erzeugt die Toolkette zu jeder Klasse, die eine oder mehrere virtuelle Funktionen deklariert oder/und implementiert, eine VMT (Virtual Method Table). Diese legt der Linker / Lokator üblicherweise in den Programmspeicher. Die VMT enthält die Funktionseinsprung-Adressen zu den klassenspezifischen Funktionsimplementierungen.

2. Datenspeicher und Laufzeit

Objekte, instanziiert aus einer Klasse mit virtuellen Funktionen, enthalten als zusätzliches, erstes Attribut die Einsprung-Adresse in dessen Klassen-VMT. Dieses Attribut fügt der Compiler automatisch hinzu, und der Konstruktor initialisiert es ebenfalls automatisch.

3. Laufzeit

Beim Aufruf einer virtuellen Funktion für ein bestimmtes Objekt über einen Zeiger oder eine Referenz wird über dessen VMT-Einsprung-Adresse die Funktionsadresse aus der VMT gelesen und anschließend zu dieser Funktionsadresse gesprungen (-> eine In-Direktion mehr als beim Aufruf nicht-virtueller Funktionen). Dies ist die Funktionalität der dynamischen Bindung. Sie erlaubt so die Programmierung der dynamischen Polymorphie. Diesen Mechanismus führt die C++ Toolkette automatisch aus. In C ist die dynamische Bindung mit etwas mehr Programmieraufwand manuell nachbildbar.

Thomas

Batt

Trainer und Coach

MicroConsult

Thomas Batt verantwortet bei MicroConsult als zertifizierter Trainer und Coach die Themenbereiche Systems/ Software Engineering für Embedded-/Realtime-Systeme sowie Entwicklungsprozess-Beratung.
Anzeige

Weitere Artikel

Newsletter
Newsletter Box

Mit Klick auf den Button "Jetzt Anmelden" stimme ich der Datenschutzerklärung zu.