Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Die Basis der Objektorientierung
3 Die Prinzipien des objektorientierten Entwurfs
4 Die Struktur objektorientierter Software
5 Vererbung und Polymorphie
6 Persistenz
7 Abläufe in einem objektorientierten System
8 Module und Architektur
9 Aspekte und Objektorientierung
10 Objektorientierung am Beispiel: Eine Web-Applikation mit PHP 5 und Ajax
A Verwendete Programmiersprachen
B Literaturverzeichnis
Stichwort
Ihre Meinung?

Spacer
 <<   zurück
Objektorientierte Programmierung von Bernhard Lahres, Gregor Rayman
Das umfassende Handbuch
Buch: Objektorientierte Programmierung

Objektorientierte Programmierung
2., aktualisierte und erweiterte Auflage, geb.
656 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1401-8
Pfeil 7 Abläufe in einem objektorientierten System
  Pfeil 7.1 Erzeugung von Objekten mit Konstruktoren und Prototypen
    Pfeil 7.1.1 Konstruktoren: Klassen als Vorlagen für ihre Exemplare
    Pfeil 7.1.2 Prototypen als Vorlagen für Objekte
    Pfeil 7.1.3 Entwurfsmuster »Prototyp«
  Pfeil 7.2 Fabriken als Abstraktionsebene für die Objekterzeugung
    Pfeil 7.2.1 Statische Fabriken
    Pfeil 7.2.2 Abstrakte Fabriken
    Pfeil 7.2.3 Konfigurierbare Fabriken
    Pfeil 7.2.4 Registraturen für Objekte
    Pfeil 7.2.5 Fabrikmethoden
    Pfeil 7.2.6 Erzeugung von Objekten als Singletons
    Pfeil 7.2.7 Dependency Injection
  Pfeil 7.3 Objekte löschen
    Pfeil 7.3.1 Speicherbereiche für Objekte
    Pfeil 7.3.2 Was ist eine Garbage Collection?
    Pfeil 7.3.3 Umsetzung einer Garbage Collection
  Pfeil 7.4 Objekte in Aktion und in Interaktion
    Pfeil 7.4.1 UML: Diagramme zur Beschreibung von Abläufen
    Pfeil 7.4.2 Nachrichten an Objekte
    Pfeil 7.4.3 Iteratoren und Generatoren
    Pfeil 7.4.4 Funktionsobjekte und ihr Einsatz als Eventhandler
    Pfeil 7.4.5 Kopien von Objekten
    Pfeil 7.4.6 Sortierung von Objekten
  Pfeil 7.5 Kontrakte: Objekte als Vertragspartner
    Pfeil 7.5.1 Überprüfung von Kontrakten
    Pfeil 7.5.2 Übernahme von Verantwortung: Unterklassen in der Pflicht
    Pfeil 7.5.3 Prüfungen von Kontrakten bei Entwicklung und Betrieb
  Pfeil 7.6 Exceptions: Wenn der Kontrakt nicht eingehalten werden kann
    Pfeil 7.6.1 Exceptions in der Übersicht
    Pfeil 7.6.2 Exceptions und der Kontrollfluss eines Programms
    Pfeil 7.6.3 Exceptions im Einsatz bei Kontraktverletzungen
    Pfeil 7.6.4 Exceptions als Teil eines Kontraktes
    Pfeil 7.6.5 Der Umgang mit Checked Exceptions
    Pfeil 7.6.6 Exceptions in der Zusammenfassung

In diesem Kapitel beschäftigen wir uns mit dem Verhalten von Objekten zur Laufzeit eines Programms. Wir begleiten Objekte vom Zeitpunkt ihrer Erzeugung über ihre hoffentlich sinnvollen Interaktionen bis zum Ende ihres Lebens, an dem sie oft nur als ein Stück Abfall angesehen werden und von der »Müllabfuhr« (der Garbage Collection) aufgesammelt werden.

7 Abläufe in einem objektorientierten System

Die Art, wie wir Objekte erzeugen, ist ganz entscheidend für die Qualität von objektorientierten Systemen. Der Mechanismus der dynamischen Polymorphie bietet uns eine Möglichkeit, unsere Programme änderbar und erweiterbar zu gestalten. Wenn Sie sich aber bei der Objekterzeugung auf zu starre Mechanismen einlassen, haben Sie diesen Vorteil schnell wieder verspielt. Um die Vorteile der Polymorphie wirklich für Erweiterungen nutzen zu können, müssen Sie die Stellen, an denen Objekte erzeugt werden, als mögliche Erweiterungspunkte betrachten.

Aufbau des Kapitels

In Abschnitt 7.1 gehen wir deshalb zunächst auf die grundlegenden Möglichkeiten der Objekterzeugung ein: die Erzeugung von Objekten über Konstruktoren oder Prototypen. Eine der beiden Möglichkeiten wird von den objektorientierten Programmiersprachen meist direkt bereitgestellt.

Diese beiden Möglichkeiten alleine reichen aber nicht aus, um Programme flexibel zu gestalten. In Abschnitt 7.2 gehen wir deshalb auf das Thema der Objekt-Fabriken ein. Dort beschreiben wir, wie wir die Möglichkeiten der Objekterzeugung verwenden sollten, um unsere Programme flexibel und erweiterbar zu halten. Abschnitt 7.3 beschäftigt sich damit, wie Objekte wieder gelöscht werden. In Abschnitt 7.4 sind die verschiedenen Formen von Interaktion zwischen Objekten das Thema. Schließlich beschäftigen wir uns in den Abschnitten 7.5 und 7.6 mit der Prüfung von Kontrakten zwischen Objekten und der Rolle von Exceptions bei dieser Prüfung.


Rheinwerk Computing - Zum Seitenanfang

7.1 Erzeugung von Objekten mit Konstruktoren und Prototypen  Zur nächsten ÜberschriftZur vorigen Überschrift

Grundsätzlich gibt es zwei verschiedene Möglichkeiten, Objekte zu erzeugen und zu initialisieren. Das zu verwendende Verfahren wird dabei meist durch die Programmiersprache exklusiv vorgegeben:

Zwei Möglichkeiten der Objekterstellung

  • Erzeugung von Objekten über Klassenmethoden, sogenannte Konstruktoren. Diese bieten in der Regel auch Initialisierungsmöglichkeiten für Objekte.
  • Erzeugung von Objekten über das Kopieren von Prototypen. Dabei dienen Objekte als Basis für das Erstellen von weiteren Objekten. Prototypen sind außerdem ein Entwurfsmuster, das sich auch in Sprachen umsetzen lässt, die selbst nicht prototypbasiert sind.

In den folgenden beiden Abschnitten werden wir zunächst den Ansatz der Konstruktoren und dann den Ansatz der Prototypen vorstellen.


Rheinwerk Computing - Zum Seitenanfang

7.1.1 Konstruktoren: Klassen als Vorlagen für ihre Exemplare  Zur nächsten ÜberschriftZur vorigen Überschrift

In den meisten Programmiersprachen werden Objekte über Konstruktoren erzeugt. Bereits in Abschnitt 4.2.6, »Klassenbezogene Methoden und Attribute«, haben wir Konstruktoren als Operationen von Klassen eingeführt. Die Definition eines Konstruktors wiederholen wir an dieser Stelle, um Ihnen das Zurückblättern zu ersparen.


Icon Hinweis Konstruktor

Konstruktoren sind Operationen einer Klasse, durch die Exemplare dieser Klasse erstellt werden können. Die Klassendefinition dient dabei als Vorlage für das durch den Aufruf einer Konstruktoroperation erstellte Objekt.


Bei Verwendung eines Konstruktors stellt die jeweilige Klasse eine Vorlage für die Objekte dar und definiert die Eigenschaften der Objekte. Ist ein Objekt aufgrund dieser Vorlage einmal erstellt, kann die Menge seiner grundsätzlichen Eigenschaften in der Regel nicht mehr verändert werden. Sie können zum Beispiel nach der Erzeugung keine neuen Eigenschaften und Operationen mehr zum Objekt hinzufügen, da die Klasse diese als Vorlage bereits eindeutig definiert. [Es gibt allerdings Programmiersprachen wie Ruby oder Python, die auch das zulassen. ]

Schauen Sie sich also ein sehr einfaches Beispiel eines Konstruktors in der Sprache C++ einmal etwas genauer an. In Abbildung 7.1 sehen Sie zwei Klassen von Teigwaren mit jeweils zugeordneten Konstruktoren. Damit wir dieses Buch bei Amazon auch zusätzlich in der Kategorie Kochbuch einsortieren können, werden wir mit dem verwendeten Konstruktor das beliebte schwäbische Gericht Spätzle herstellen.

Abbildung 7.1    Konstruktoren für Teigwaren

In Listing 7.1 ist die Umsetzung der drei verschiedenen Konstruktoren für die Klasse Spaetzle in C++ aufgeführt.

class Spaetzle:  public Teigware 
{ 
    // ... 
private: 
    Herstellungsart art; 
public: 
    // Standardkonstruktor 
    Spaetzle() {};   
    // Konstruktor mit Initialisierung 
    Spaetzle(Herstellungsart art) : art(art) {};  
    // Copy-Konstruktor 
    Spaetzle(const Spaetzle& spaetzle) :   
         Teigware(spaetzle), art(spaetzle.art) {}; 
    // ... 
};

Listing 7.1    Konstruktoren für Spaetzle-Objekte

Die verwendeten Konstruktoren gehören drei verschiedenen Gruppen an:

  • In Zeile wird der Standardkonstruktor ohne Parameter umgesetzt.
  • In Zeile wird ein Konstruktor umgesetzt, der zusätzlich eine Initialisierung des Objekts vornimmt.
  • In Zeile wird der sogenannte Copy-Konstruktor umgesetzt. Dieser erstellt ein neues Objekt auf Basis eines bereits existierenden Objekts.

Standardkonstruktor

Unter Verwendung des Standardkonstruktors können Sie nun ein Exemplar der Klasse Spaetzle erzeugen:

Spaetzle abendessen = new Spaetzle();

Damit haben Sie ein Objekt konstruiert, dessen Datenelemente durch die beiden beteiligten Klassen Spaetzle und Teigwaren festgelegt sind. Das neu konstruierte Objekt unterstützt außerdem alle Operationen, für welche die beiden Klassen Methoden implementiert haben.

Das Einzige, was wir am Objekt nach dessen Konstruktion noch ändern können, sind dessen konkrete Daten, also die Belegungen für die von der Klasse definierten Datenelemente. [Auch hier gilt wieder, dass einige Sprachen wie Python oder Ruby es zulassen, dass später noch weitere Methoden oder Eigenschaften einem Objekt hinzugefügt werden. ]

Konstruktor mit Initialisierung

Zusätzlich zur Objektkonstruktion können Sie im gleichen Zug noch Belegungen für Attribute des Objekts mit angeben. Welche Initialisierung möglich ist, wird durch den Konstruktor festgelegt. Im Fall der Klasse Spaetzle haben Sie dafür einen zweiten Konstruktor zur Verfügung, der einen Parameter für die Herstellungsart der Spätzle definiert.

Spaetzle(Herstellungsart art) : art(art) {};

Dabei wird das Datenelement art, das durch die Klasse festgelegt wird, mit dem übergebenen Wert für die Herstellungsart belegt. Der konkrete Aufruf des Konstruktors könnte dann so aussehen:

Spaetzle leckerEssen = new Spaetzle(enHandgeschabt);

In Abbildung 7.2 ist das resultierende Exemplar zu sehen. Es sind die beiden Datenelemente vorhanden, die durch die beiden beteiligten Klassen definiert werden, das Datenelement art ist mit dem bei der Initialisierung verwendeten Wert belegt.

Die UML-Darstellung sieht leider nicht die Möglichkeit vor, die Operationen auch für die Objekte anzeigen zu lassen. Das Objekt leckeresEssen unterstützt aber die beiden Operationen setzeHerstellungsart und Hersteller.

Abbildung 7.2    Ein Exemplar der Klasse »Spaetzle«, Objekt »leckeresEssen«

Copy-Konstruktor

Eine besondere Art der Objektkonstruktion realisiert der sogenannte Copy-Konstruktor, der ein neues Objekt auf der Grundlage eines bereits existierenden Objekts erstellt und dessen Daten übernimmt.

    Spaetzle* essen = 
        new Spaetzle(Spaetzle::enSpaetzlesDruecker); 
    Spaetzle* leckeresEssen = new Spaetzle(*essen); 
    leckerEssen->setzeHerstellungsart( 
        Spaetzle::enHandgeschabt);

Durch die Verwendung des Copy-Konstruktors erhalten Sie eine 1:1-Kopie Ihres Essens, eine Spätzle-Kopie (in diesem Fall eine zweite Portion Spätzle). Diese Kopie können Sie anschließend anpassen und so zum Beispiel aus einem guten ein richtig leckeres Essen machen. Im Fall unserer Spätzle ist diese Kopie auch recht einfach zu erstellen. Sofern Objekte wiederum andere Objekte referenzieren, müssen Sie sich aber entscheiden, ob sie von diesen Objekten selbst wieder Kopien anfertigen wollen oder nur den Verweis auf das Objekt kopieren.

Diese beiden Alternativen werden tiefe und flache Kopien genannt. Wir beschäftigen uns damit genauer in Abschnitt 7.4.5, »Kopien von Objekten«. [Die meisten Programmiersprachen stellen für jede Klasse einen Copy-Konstruktor auch dann bereit, wenn dieser nicht explizit umgesetzt wird. Dieser vordefinierte Copy-Konstruktor wird allerdings nur flache Kopien von Objekten anlegen. ]


Rheinwerk Computing - Zum Seitenanfang

7.1.2 Prototypen als Vorlagen für Objekte  Zur nächsten ÜberschriftZur vorigen Überschrift

Beim klassenbasierten Ansatz der Objekterzeugung definiert die Klasse bei der Erzeugung bereits die Struktur des erzeugten Objekts. Bei der Erzeugung wird damit schon festgelegt, welche Eigenschaften und Methoden das Objekt hat, und diese sind dann in der Regel auch nicht mehr veränderbar. Die Klasse bestimmt, wie das erzeugte Objekt von seiner Struktur her aussieht. Das ist aber nur ein mögliches Vorgehen. Die andere Möglichkeit ist es, Objekte auf Basis von Prototypen zu erstellen und die konkrete Ausprägung der Objekte erst danach durchzuführen.


Icon Hinweis Prototyp

Ein Prototyp im Bereich der objektorientierten Programmierung ist ein Objekt, das als Vorlage für die Erstellung von anderen Objekten dient. Die Vorlage kann dabei entweder als reine Kopiervorlage oder als mitgeführte Referenz verwendet werden.


In der Sprache JavaScript werden Prototypen verwendet, um Vererbungsbeziehungen zu ermöglichen, ohne dass überhaupt Klassen zum Einsatz kommen. Dafür werden Prototyp-Objekte eingesetzt, die per Referenz von anderen Objekten eingebunden werden. Wir stellen diesen Ansatz der Objekterzeugung, wie er in JavaScript zu finden ist, in diesem Abschnitt kurz vor. Im nächsten Abschnitt werden wir dann auf das Entwurfsmuster »Prototyp« eingehen, bei dem Objekte als Kopiervorlagen genutzt werden.

Objekterzeugung mit JavaScript

In JavaScript wird ein Objekt zunächst einfach ohne Eigenschaften konstruiert. Anschließend wird ihm aber anderes Objekt zugeordnet, das als Vorlage dient. Dabei werden die Eigenschaften dieses Objekts komplett übernommen. Das neue Objekt hält praktisch eine Referenz auf seine Vorlage.

Bei der Verwendung von solchen Objekten greifen Sie über die Objekte auf deren Vorlagen zu. Änderungen an den Vorlagen werden so auch für die auf deren Basis erstellten Objekte sichtbar.

JavaScript kennt keine Klassen.

JavaScript kennt das Konzept der Klasse überhaupt nicht und damit natürlich auch keine auf Klassen basierende Vererbung. Dennoch lassen sich auf der Basis der sogenannten Prototypen Konzepte der objektorientierten Programmierung damit umsetzen. Auch Vererbungsbeziehungen lassen sich so umsetzen.

In Abbildung 7.3 sehen Sie eine Beispielhierarchie dargestellt. Anhand dieses Beispiels stellen wir im Folgenden kurz vor, wie sich mit JavaScript die dargestellten Beziehungen auch ohne Klassen realisieren lassen.

Abbildung 7.3    Hierarchie für JavaScript-Beispiel

JavaScript: Objekte und Funktionsobjekte

Anstelle von Klassen werden dabei Funktionen verwendet, die zur Initialisierung von Objekten dienen. Funktionen sind allerdings in JavaScript selbst Objekte, die Eigenschaften haben können, und werden Funktionsobjekte genannt. Wenn Sie diese Funktionen zusammen mit dem Operator new aufrufen, werden sie als Konstruktoren genutzt. Es wird dann ein neues Objekt erstellt, das die durch die Funktion beschriebene Initialisierung durchläuft. Funktionsobjekte wiederum haben selbst ein weiteres Objekt zugeordnet, das als Prototyp fungiert. Bei der Objekterstellung über eine Funktion wird dieser Prototyp auch dem erstellten Objekt zugeordnet.

Betrachten wir dieses Vorgehen anhand der Umsetzung unserer Beispielhierarchie aus Abbildung 7.3. In Listing 7.2 sind die Umsetzung und Verwendung dieser Hierarchie zu sehen.

function Basis()  
{ 
    this.beschreiben = function ()  
    { 
        alert(" Beschreibung der Basis"); 
    } 
} 
 
function Abgeleitet()  
{ 
} 
 
basis = new Basis();  
Abgeleitet.prototype = basis;  
 
abgeleitet1 = new Abgeleitet();   
abgeleitet2 = new Abgeleitet(); 
abgeleitet1.beschreiben(); // Ausg.: Beschreibung der Basis 
abgeleitet2.beschreiben(); // Ausg.: Beschreibung der Basis

Listing 7.2    Verwendung von Prototypen in JavaScript

In Zeile wird eine Funktion definiert, mit der Objekte initialisiert werden können. In Zeile wird festgelegt, dass jedes dieser Objekte eine Operation beschreiben haben wird, deren Implementierung dort auch festgelegt wird. In Zeile wird eine weitere Funktion Abgeleitet definiert, die zunächst noch in keiner Beziehung zu der anderen Funktion steht. In Zeile wird ein Objekt basis auf Grundlage der bereits definierten Funktion Basis erstellt. In Zeile wird dem Funktionsobjekt Abgeleitet dieses neue Objekt als Prototyp zugeordnet. Dies geschieht über die Eigenschaft prototype, die alle Funktionsobjekte aufweisen. In der Folge werden alle über diese Funktion initialisierten Objekte (zum Beispiel die ab Zeile erstellten) auch alle Eigenschaften und Operationen des Objekts basis besitzen.

Wenn nun die Operation beschreiben auf den beiden Objekten aufgerufen wird, so wird die Methode beschreiben ausgeführt, die dem Objekt basis zugeordnet ist. Beim Aufruf einer Operation wird nämlich die Kette der Prototypen eines Objekts durchlaufen, um festzustellen, ob einer der Prototypen die erforderliche Eigenschaft aufweist. Da in dieser Kette das Objekt basis die Methode beschreiben umsetzt, werden Sie also für beide Aufrufe die Ausgabe erhalten »Beschreibung der Basis«.

Sie können das Verhalten eines Objekts nun modifizieren, indem Sie ihm selbst weitere Datenelemente oder Methoden zuordnen. Sie können das Verhalten des Objekts aber auch ändern, indem Sie seinen Prototyp anpassen. Wenn mehrere Objekte denselben Prototyp zugeordnet haben, wird eine Änderung an diesem Prototyp das Verhalten von allen diesen Objekten modifizieren.

basis.beschreiben = function () 
    { 
       alert("keine Lust mehr, keine Beschreibung"); 
    } 
abgeleitet1.beschreiben(); // Ausg.: keine Lust mehr, ... 
abgeleitet2.beschreiben(); // Ausg.: keine Lust mehr, ...

Listing 7.3    Änderung an Prototyp

JavaScript: Erweiterung von Objekten

In Listing 7.3 ist eine solche Anpassung zu sehen. Die Implementierung der Methode beschreiben wird für den Prototyp neu umgesetzt.

Sie haben mit dieser Anweisung den Prototyp von beiden Objekten abgeleitet1 und abgeleitet2 verändert. Damit werden sich nun beide Objekte bockig stellen und mit Verweis auf ihren Prototyp beim Aufruf von beschreiben nur noch ausgeben "keine Lust mehr, keine Beschreibung".

Vererbung in JavaScript

Da offensichtlich die beiden abgeleiteten Objekte die Eigenschaften ihres Prototyps übernommen, also mit anderen Worten geerbt haben, erhalten Sie einen Mechanismus, mit dem sich einige Aspekte der Vererbung auch in JavaScript umsetzen lassen. Durch eine Kette von Prototypen und zugehörigen Funktionen lassen sich Hierarchien aufbauen.

Bei der Konstruktion eines Objekts über new FunctionName wird dem neu erstellten Objekt eine interne Referenz auf einen Prototyp mitgegeben, der durch den Prototyp des verwendeten Funktionsobjekt bestimmt wird. Haben Sie dem Funktionsobjekt nichts anderes mitgeteilt, ist das der Prototyp der Funktion Object(). Sie können dem Funktionsobjekt aber auch explizit einen anderen Prototyp zuordnen, wie Sie bereits in Listing 7.2 gesehen haben.

Um den technischen Mechanismus einer Kette von Prototypen zu illustrieren, erweitern wir die Hierarchie unseres Beispiels noch etwas. In Abbildung 7.4 ist diese erweiterte Hierarchie dargestellt.

Hierarchie von Prototypen

Der Code in Listing 7.4 erzeugt nun genau diese Hierarchie.

function Basis() {} 
function AbgeleitetA() {} 
function WeiterAbgeleitetB() {} 
basis = new Basis(); 
AbgeleitetA.prototype = basis; 
abgeleitetA = new AbgeleitetA(); 
WeiterAbgeleitetB.prototype = abgeleitetA; 
weiterabgeleitetB = new WeiterAbgeleitetB();

Listing 7.4    Erweiterte Hierarchie für Prototypen

Abbildung 7.4    Erweiterte Hierarchie für Prototypen

Das Objekt weiterabgeleitetB wird unter Verwendung des Funktionsobjekts WeiterAbgeleitetB erzeugt. Damit weist das Objekt eine Kette von Prototypen auf. Der Prototyp abgeleitetA ist dem Objekt weiterabgeleitetB direkt zugeordnet, weil dieser auch dem Funktionsobjekt zugeordnet ist. In Abbildung 7.5 ist die resultierende Kette dargestellt.

Abbildung 7.5    Kette von Prototypen in JavaScript

Prototypen sind dabei immer Objekte (keine Funktionsobjekte). Die Prototypen werden referenziert von anderen Objekten oder von Funktionsobjekten. Wird nun eine Operation auf dem Objekt aufgerufen, wird zuerst geprüft, ob das Objekt selbst eine Methode für diese Operation aufweist.

Bei einem Aufruf der Operation toString auf dem Objekt weiterabgeleitetB startet eine Suche auf den beteiligten Objekten.

Da das Objekt selbst diese Methode nicht umgesetzt hat, wird sie im ersten Prototyp der Kette gesucht.

Dies ist im Fall unseres Objekts derjenige, der über die Funktion AbgeleitetA erstellt wurde und unserer Variablen abgeleitetA zugewiesen worden ist. Wird die Methode dort gefunden, wird sie auch aufgerufen. Aber auch hier ist keine Methode toString vorhanden. Deshalb geht die Suche über den zugeordneten Prototyp weiter, bis eine Methode gefunden wird oder das Ende der Kette von Prototypen erreicht ist. Im Fall des Aufrufs von toString haben Sie gerade noch Glück: Das letzte Element der Kette (das über die Funktion Object() erstellte Objekt) im-plementiert die Methode, und Sie erhalten eine Beschreibung geliefert, wenn auch eine sehr unspezifische. Wenn sich auch das letzte Element der Kette nicht zuständig erklärt, kommt es zu einem Laufzeitfehler.

Vererbungskette

Damit erlaubt JavaScript ein Vererbungsverfahren, das rein auf Objekten basiert. Wenn ein Prototyp in der Kette eine Eigenschaft oder eine Operation definiert, kann diese von allen auf dessen Basis erstellten Objekten genutzt werden. Diese Methoden und Eigenschaften können jedoch auch überschrieben werden, wenn sie ein Objekt selbst oder ein Prototyp weiter vorne in der Kette neu definiert.

Ein weiterer Aspekt dieser Vorgehensweise ist es, dass Objekte und deren Prototypen zur Laufzeit des Programms angepasst werden können. Da es keinerlei feste Vorlagen für die Objekte gibt, können sie nach ihrer Erstellung munter weiter mit zusätzlichen Eigenschaften und Methoden ausgestattet werden. Dabei können auch die verwendeten Prototypen nachträglich erweitert werden, so dass alle auf deren Basis erstellten Objekte danach erweiterte oder veränderte Fähigkeiten aufweisen. [Dieser Mechanismus ist sehr flexibel, aber auch schwer zu kontrollieren. Da über jedes Objekt das Verhalten einer ganzen Menge von Objekten geändert werden kann, ohne dass diese Änderung offensichtlich wird, können hier leicht Seiteneffekte entstehen. JavaScript bietet allgemein kaum Mittel, um Datenabstraktion und Kapselung zu unterstützen. ]

Offensichtlich nicht möglich ist hier Mehrfachvererbung, da es immer nur ein Attribut prototype für eine Funktion gibt.


Rheinwerk Computing - Zum Seitenanfang

7.1.3 Entwurfsmuster »Prototyp«  topZur vorigen Überschrift

Prototypen finden ihre Anwendung auch im gleichnamigen Entwurfsmuster. Dort haben Prototypen aber eine etwas andere Funktion. Sie dienen hier als Kopiervorlage, auf deren Basis neue Objekte erzeugt werden.


Icon Hinweis Entwurfsmuster »Prototyp«

Bei Verwendung des Entwurfsmusters »Prototyp« wird eine Sammlung von Objekten als Vorlagen verwaltet. Wird ein neues Objekt benötigt, wird aus den Vorlagen ein Objekt ausgewählt und eine Kopie davon erzeugt. Diese ist zunächst gleich mit dem Original und kann anschließend verändert werden.


Abbildung 7.6    Entwurfsmuster »Prototyp« mit Verwalter

In Abbildung 7.6 sind die Beziehungen zwischen den Klassen des Entwurfsmusters dargestellt. In dieser Darstellung sehen Sie bereits eine Erweiterung des Musters, bei der ein Verwalter für die Prototypen zum Einsatz kommt. Die zentrale Idee ist dabei sehr einfach: Sie haben eine Reihe von Klassen, die alle eine Schnittstelle implementieren. Diese Schnittstelle spezifiziert auch eine Operation, die es erlaubt, dass die Exemplare der Klassen Kopien von sich selbst erzeugen. Sie erzeugen dann von jeder Klasse ein prototypisches Exemplar. Auf Anforderung erzeugt dieses Exemplar eine Kopie von sich selbst, diese stellen Sie dem nutzenden Modul zur Verfügung.

Im abgebildeten Szenario der Abbildung 7.6 werden die erstellten Vorlagenexemplare zentral von einer Klasse PrototypVerwalter gesammelt und mit einem Schlüsselwert assoziiert. Auf Anfrage mit übergebenem Schlüssel gibt ein Exemplar des PrototypVerwalters dann eine Kopie des mit dem Schlüssel assoziierten Prototyps zurück.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  Zum Rheinwerk-Shop
Neuauflage: Objektorientierte Programmierung






Neuauflage:
Objektorientierte Programmierung

Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: Einstieg in Python






 Einstieg in Python


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern