Ausgangspunkt der heutigen Überlegungen sind Tabellen in Datenbanken. Hier werden den Datensätzen gerne eindeutige IDs zugewiesen. Dafür gibt es das Mittel der Indizierung, so spielt die Festlegung eines Primärschlüssels eine wichtige Rolle.
Mit einem Primärschlüssel verbunden ist die Überprüfung, ob der einzutragende Datensatz in die Tabelle durchgeführt werden kann oder nicht. So wie im nachstehenden Beispiel:

Die Id eines Mitarbeiters muss hier eindeutig sein. Wenn ich nun einen Mitarbeiter mit einer ID=4 eintragen möchte, so wird dies abgelehnt, da diese Nummer schon existiert.
Soweit die Datenbanken … aber wie setze ich ein solches Verhalten in einer objektorientierten Programmierung wie C# um?
Tabelle und Klasse
Jeder Datensatz in einer Tabelle ist ein Objekt. Und so, wie die Spalten einer Tabelle die Eigenschaften eines Objektes festlegen, so können in einer Klasse auch Objekteigenschaften definiert werden.
Somit könnte man entsprechend obigem Beispiel der Tabelle Mitarbeiter eine Klasse wie folgt entwerfen:

Da die ma_id eindeutig sein muss, muss die Klasse “überwachen”, dass hier keine doppelten Werte vergeben werden. Daher ist der schreibende, und damit auch lesende, Zugriff verwehrt.
Konstruktor und Klassenvariable
Auch der ma_id muss ein Wert zugewiesen werden können. Da der Zugriff allerdings auf die eigene Klasse beschränkt ist, bleibt nur der Konstruktor.

Eine Klassenvariable zählt die Anzahl der erzeugten Objekte. Jedes Objekt erhält eine eindeutige, fortlaufende Nummer, welche sich aus der Anzahl der Objekte ableitet. Nachfolgend der Code in C#:
class Mitarbeiter{
private static int anzahl=0;
private int ma_id;
public string nachnameK
public double gehalt;
public string abteilung;
public Mitarbeiter{
ma_id=++anzahl;
}
}
Mmh … das funktioniert sehr gut. Doch was ist, wenn ich einem Mitarbeiter keine fortlaufende Nummer geben möchte, sondern eine individuelle?
Nun, ich könnte den Konstruktor so gestalten, dass bei Erzeugung eines Objektes eine Nummer angegeben werden muss.
Hier ein alternativer Konstruktor:
public Mitarbeiter(int id){ma_id = id;}
Nun, dann könnte man bei der Erzeugung von Objekten wiederum die gleiche ID vergeben … das wäre ein Rückschritt.
Mitarbeiter m1 = new Mitarbeiter(42);
Mitarbeiter m2 = new Mitarbeiter(42); //das darf nicht sein
Innerhalb des Konstruktors eine Prüfung vorzunehmen, ob die übergebene ID schon vorhanden ist, geht nicht, weil jedes Objekt nur seine eigenen Eigenschaftswerte kennt. Die IDs der anderen erzeugten Objekte sind also nicht zugänglich.
Die Idee
- Wir brauchen eine Instanz, welche alle bisher vergebenen IDs für Mitarbeiter-Objekte speichert.
- soll ein neues Objekt der Klasse Mitarbeiter erzeugt wird, wird zunächst geprüft, ob die gewünschte ID schon vergeben ist
- Wenn ja, dann erfolgt eine Objektinstanziierung.
Erstellen wir eine Liste, in welcher alle schon vergebenen IDs gespeichert sind:
List<int> id_liste = new List<int>();
Jedesmal, bevor wir ein Objekt der Klasse Mitarbeiter erzeugen, prüfen wir, ob die ID schon in dieser Liste gespeichert ist. Wenn also eine 3 vergeben werden soll, dann wird so geprüft:
bool gotIt = id_liste.Contains(3);
Anschließend erzeuge ich nur dann ein Objekt, wenn die Methode Contains() den Wert false zurückgibt.
if(gotIt == false) Mitarbeiter m = new Mitarbeiter(3);
Das Problem
Wir müssen im Programmablauf darauf achten, dass wir immer VOR der Instanziierung eines Objektes die Prüfung durchführen.
Wir können weiterhin ein Objekt erzeugen, ohne eine Liste anzulegen und diese auf ihren Inhalt zu testen.
Somit ist es weiterhin möglich, zwei Mitarbeiter mit der gleichen ID im Programm zu haben.
Die Lösung – Fabrikmethode
Wir erstellen eine Fabrik, welche die Erzeugung der Mitarbeiter übernimmt. Dazu wird das Zugriffsrecht auf den Konstruktor der Klasse Mitarbeiter eingeschränkt.

Wir erstellen eine Klassenbibliothek (in C#, in java ein Paket) mit zwei Klassen. Die Fabrik erhält eine öffentlich zugängliche Methode, welche Objekte der Klasse Mitarbeiter erzeugt. Auch die Prüfung, ob IDs schon vergeben sind, erfolgt in der Fabrik. Dazu hat diese eine private Liste mit allen bisherigen IDs.
Der Konstruktor der Klasse Mitarbeiter ist nur noch innerhalb der Klassenbibliothek (dll – in C#, Paket in java) sichtbar.

Das Schlüsselwort internal bewirkt in C#, dass der Zugriff auf die eigene Klassenbibliothek beschränkt wird. In java würde man hier das default-Zugriffsrecht oder auch protected verwenden.
Soll nun in einem Programmablauf ein Mitarbeiter erzeugt werden, so kann dies nur über die Fabrik erfolgen.

Die Objektreferenz m2 verweist auf null, da aufgrund der gleichen ID kein Objekt erzeugt werden konnte.