제이온

[Objekt] Kapitel 2. Objektorientierte Programmierung

  • Verfasst in: Koreanisch
  • Land: Alle Ländercountry-flag
  • IT

Erstellt: 2024-04-28

Erstellt: 2024-04-28 13:46

Filmreservierungssystem


Anforderungen prüfen

  • Wir wollen ein Online-Filmreservierungssystem implementieren.
  • Ein Film repräsentiert die Basisinformationen zu einem Film.
    • Titel, Laufzeit, Preisinformationen usw.
  • Eine Vorführung repräsentiert das tatsächliche Ereignis, bei dem das Publikum den Film sieht.
    • Datum der Vorführung, Uhrzeit, Nummer der Vorführung usw.
  • Menschen reservieren zwar Filme, aber eigentlich sollten sie eine bestimmte Vorführungeines Films reservieren.
  • Rabattbedingungen
    • Ob der Preis reduziert wird
    • Reihenfolgebedingung: Die Nummer der Vorführung wird verwendet, um zu bestimmen, ob ein Rabatt gewährt wird
    • Zeitbedingung: Der Beginn der Filmvorführung wird verwendet, um zu bestimmen, ob ein Rabatt gewährt wird
  • Rabattpolitik
    • Ermittlung des Rabattpreises
    • Festbetragsrabattpolitik: Ein bestimmter Betrag wird vom Reservierungspreis abgezogen
    • Prozentualer Rabattpolitik: Ein bestimmter Prozentsatz des regulären Preises wird abgezogen
  • Jedem Film kann eine Rabattpolitik zugewiesen werden oder gar keine, und die Rabattbedingungen können aus mehreren Rabattbedingungen bestehen.
  • Wenn eine Rabattpolitik angewendet wird, aber die Rabattbedingungen nicht erfüllt sind oder keine Rabattpolitik angewendet wird, wird der Preis nicht reduziert.


Auf dem Weg zur objektorientierten Programmierung

Zusammenarbeit, Objekte, Klassen

  • Objektorientiert bedeutet, Objekte zu orientieren.
    • Man sollte nicht zuerst die Klasse festlegen und dann überlegen, welche Attribute und Methoden die Klasse benötigt.
    • Man muss entscheiden, welche Objekte welchen Zustand und welches Verhalten haben.
    • Objekte sollten nicht als unabhängige Entitäten betrachtet werden, sondern als Mitglieder einer kooperierenden Gemeinschaft.


Programstruktur, die der Struktur des Domäns folgt

  • Der Domän ist der Bereich, in dem der Benutzer das Programm verwendet, um ein Problem zu lösen.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe7d22a03-4a24-40e9-8068-bd03b9fd816b%2FUntitled.png?table=block&id=3f1931fc-8ef9-470a-8189-3727146638f6&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/438;" width="2000" height="438"></span>

  • Im Allgemeinen sollte der Name einer Klasse dem Namen des entsprechenden Domänenkonzepts entsprechen oder zumindest ähnlich sein.
  • Auch die Beziehungen zwischen den Klassen sollten so weit wie möglich den Beziehungen zwischen den Domänenkonzepten entsprechen, damit die Struktur des Programms leicht verständlich und vorhersagbar ist.


Klassen implementieren

  • Eine Klasse wird in einen internen und einen externen Bereich unterteilt, und um eine gute Klasse zu entwerfen, muss man entscheiden, welcher Teil nach außen verfügbar sein soll und welcher Teil verborgen bleiben soll.
    • Die Attribute eines Objekts werden durch private (privat) geschützt, und die notwendigen Methoden zur Änderung des internen Zustands werden durch public (öffentlich) freigegeben.
  • Die Trennung zwischen dem Inneren und Äußeren einer Klasse gewährleistet die Autonomie des Objekts und gibt dem Programmierer somit Freiheit bei der Implementierung.


Autonome Objekte

  • Ein Objekt sollte ein autonomes Objekt mit Zustand und Verhalten sein.
  • Das Zusammenfassen von Daten und Funktionen innerhalb eines Objekts wird als Kapselung bezeichnet.
  • Durch Zugriffskontrolle kann die Einmischung von außen reduziert werden, sodass das Objekt sein Verhalten selbst bestimmen kann.
  • Die Trennung von Schnittstelle und Implementierung ist ein wichtiges Prinzip, das bei der objektorientierten Programmierung befolgt werden sollte.
    • Öffentliche Schnittstelle: Der von außen zugängliche Teil
    • Implementierung: Der nur intern zugängliche Teil


Freiheit des Programmierers

  • Die Rolle des Programmierers wird in Klassenautoren und Client-Programmierer unterteilt.
    • Klassenautoren fügen einen neuen Datentyp hinzu
    • Client-Programmierer verwenden den vom Klassenautoren hinzugefügten Datentyp
  • Implementierungsverdeckung
    • Der Klassenautor kann die interne Implementierung verbergen, indem er dem Client-Programmierer nur die notwendigen Teile zur Verfügung stellt.
    • Der Client-Programmierer muss nur die Schnittstelle kennen, wodurch der Wissensbedarf reduziert wird.


Eine Gemeinschaft zusammenarbeitender Objekte

  • Um Geld darzustellen, ist es besser, es nicht einfach als Variable vom Typ Long zu deklarieren, sondern es in ein Objekt wie Money (Geld) zu verpacken. Durch die Verwendung von Objekten wird die Bedeutung besser vermittelt und redundante Berechnungen können an einem Ort durchgeführt werden.
  • Die Interaktion zwischen Objekten, um eine bestimmte Funktion des Systems zu implementieren, wird als Zusammenarbeit bezeichnet.


Eine kurze Geschichte über die Zusammenarbeit

  • Die einzige Möglichkeit für ein Objekt, mit anderen Objekten zu interagieren, besteht darin, Nachrichten zu senden oder zu empfangen.
  • Die eigene Methode zur Verarbeitung einer empfangenen Nachricht wird als Methode bezeichnet.
  • Die Unterscheidung zwischen Nachricht und Methode ist wichtig, und hier beginnt das Konzept des Polymorphismus.


Ermittlung des Rabattpreises

Beginn der Zusammenarbeit zur Berechnung des Rabattpreises

  • Die Klasse Movie (Film) enthält keine detaillierte Logik für die Rabattpolitik und hat diese an das Interface DiscountPolicy (Rabattpolitik) delegiert. Die Verwendung von Vererbung, Polymorphismus und Abstraktion ist hier sehr wichtig.


Rabattpolitik und Rabattbedingungen

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7b9b27a5-0dac-4ba7-9552-05b7f8fbdecd%2FUntitled.png?table=block&id=3264f189-6e12-4a55-94d2-75b851320c7a&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/535;" width="2000" height="535"></span>


Vererbung und Polymorphismus

Kompilierzeitabhängigkeit und Laufzeitabhängigkeit

  • Die Abhängigkeit des Codes und die Abhängigkeit zum Zeitpunkt der Ausführung können unterschiedlich sein.
  • Je unterschiedlicher die Abhängigkeiten sind, desto schwieriger ist es, den Code zu verstehen, aber er wird flexibler und erweiterbar.


Programmierung durch Unterschiede

  • Durch Vererbung können neue Klassen einfach und schnell basierend auf vorhandenen Klassen hinzugefügt werden, und die Implementierung der Oberklasse kann wiederverwendet werden.
  • Die Methode, eine neue Klasse zu erstellen, indem nur die unterschiedlichen Teile von der Oberklasse hinzugefügt werden, wird als Programmierung durch Unterschiede bezeichnet.


Vererbung und Schnittstellen

  • Vererbung bewirkt, dass die Unterklasse alle Schnittstellen erbt, die von der Oberklasse bereitgestellt werden.
  • Eine Schnittstelle definiert eine Liste von Nachrichten, die ein Objekt verstehen kann.
  • Movie (Film) sendet eine calculateDiscountAmount-Nachricht an DiscountPolicy (Rabattpolitik). Für Movie (Film) ist es egal, welche Klasse die Antwort gibt, es zählt nur, dass eine erfolgreiche Antwort kommt.
  • Daher können sowohl AmountDiscountPolicy (Festbetragsrabattpolitik) als auch PercentDiscountPolicy (Prozentualer Rabattpolitik) anstelle von DiscountPolicy (Rabattpolitik) mit Movie (Film) zusammenarbeiten.
  • Diese Vorgehensweise, bei der die Unterklasse die Oberklasse ersetzt, wird als Upcasting (Aufwärtskonvertierung) bezeichnet. Dies liegt daran, dass es so aussieht, als würde die Unterklasse automatisch in die Oberklasse umgewandelt werden.


Polymorphismus

  • Polymorphismus ist die Fähigkeit, auf die gleiche Nachricht je nach Objekttyp unterschiedlich zu reagieren.
    • Movie (Film) sendet die gleiche Nachricht, aber welche Methode tatsächlich ausgeführt wird, hängt davon ab, welche Klasse das Objekt empfängt, das die Nachricht empfängt.
  • Polymorphismus basiert auf der Tatsache, dass die Abhängigkeit des Programms zur Kompilierzeit und die Abhängigkeit zur Laufzeit unterschiedlich sein können.
  • Da Polymorphismus die auszuführende Methode zur Laufzeit bestimmt, wird er auch als Spätbindung oder dynamische Bindung bezeichnet.


Schnittstellen und Polymorphismus

  • Wenn die Implementierung nicht geteilt werden muss und nur die Schnittstelle geteilt werden soll, kann man stattdessen eine Schnittstelle anstelle einer abstrakten Klasse verwenden.


Abstraktion und Flexibilität

Die Kraft der Abstraktion

  • Vorteile der Abstraktion
    • Wenn man nur die Abstraktionsebenen betrachtet, kann man die Politik der Anforderungen auf hoher Ebene beschreiben.
    • Das Design wird flexibler.


Flexibles Design

  • Abstraktion verhindert, dass das Design an konkrete Situationen gebunden ist, wodurch ein flexibles Design ermöglicht wird.


Trade-off zwischen abstrakter Klasse und Schnittstelle


  • Derzeit ist NoneDiscountPolicy (Keine Rabattpolitik) eigentlich nicht notwendig, da die Methode calculateDiscountAmount() von DiscountPolicy (Rabattpolitik) bereits 0 zurückgibt, wenn keine Rabattbedingung vorhanden ist. Aber aus Sicht des Benutzers muss er der Movie (Film)-Instanz die None-Politik als Argument mitgeben, daher wurde sie hinzugefügt.
  • Daher ist die Klasse NoneDiscountPolicy (Keine Rabattpolitik) konzeptionell etwas verwirrend. Wenn man sie wie folgt ändert, ist sie leichter zu verstehen.



  • Wie oben gezeigt, wird DiscountPolicy (Rabattpolitik) als Schnittstelle abstrahiert und in NoneDiscountPolicy (Keine Rabattpolitik) als Implementierung und DefaultDiscountPolicy (Standard-Rabattpolitik) als allgemeine Rabattpolitik aufgeteilt.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F712983a9-3937-4265-82fe-66a144c44a0f%2FUntitled.png?table=block&id=f5ca651c-d03c-4a6c-97e9-7443ee5649a0&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/886;" width="2000" height="886"></span>

  • Man könnte meinen, dass das Hinzufügen einer Schnittstelle nur für NoneDiscountPolicy (Keine Rabattpolitik) im Verhältnis zum erhöhten Aufwand ineffizient ist.
  • Man muss sich bewusst sein, dass alles, was mit der Implementierung zu tun hat, Gegenstand eines Trade-offs sein kann, und man sollte das Design entsprechend gestalten. Das heißt, jeder Code, den man schreibt, sollte einen guten Grund haben.


Code-Wiederverwendung

  • Vererbung kann verwendet werden, um Code wiederzuverwenden.
  • Für die Code-Wiederverwendung ist es jedoch besser, Komposition (Zusammensetzung) anstelle von Vererbung zu verwenden.
  • Im aktuellen Code ist die Art und Weise, wie Movie (Film) den Code von DiscountPolicy (Rabattpolitik) wiederverwendet, die Komposition.
  • Wenn man Movie (Film) als Oberklasse betrachtet und sie in AmountDiscountMovie (Festbetragsrabattfilm) und PercentDiscountMovie (Prozentualer Rabattfilm) unterteilt, dann wäre dies ein Beispiel für die Verwendung von Vererbung.


Vererbung

  • Nachteile der Vererbung
    • Verletzt die Kapselung.
      • Man muss die interne Struktur der Oberklasse kennen.
      • Wenn die Oberklasse geändert wird, ist die Wahrscheinlichkeit hoch, dass auch die Unterklasse geändert werden muss.
    • Macht das Design unflexibler.
      • Die Beziehung zwischen Ober- und Unterklasse wird zur Kompilierzeit festgelegt.
      • Es ist nicht möglich, den Objekttyp zur Laufzeit zu ändern.
      • Bei der Komposition kann man jedoch zur Laufzeit die Instanz durch eine Methode wie changeDiscountPolicy() (Rabattpolitik ändern) austauschen.


Komposition

  • Die Methode, Code nur über die in der Schnittstelle definierten Nachrichten wiederzuverwenden, wird als Komposition bezeichnet.
  • Sie ermöglicht die Implementierung der Kapselung und die Aufrechterhaltung einer losen Kopplung.
  • Wenn man eine Schnittstelle für Polymorphismus wiederverwenden möchte, muss man Vererbung und Komposition kombinieren.
    • Beispielsweise muss die DiscountPolicy (Rabattpolitik)-Schnittstelle Vererbung verwenden, um Unterimplementierungen zu erstellen.


Quelle

  • Objekt

Kommentare0