Eine Einführung in Design Patterns in PHP

Veröffentlicht: 2020-04-14

PHP-Designmuster haben sich für Entwickler als äußerst nützlich erwiesen und sind ein wichtiger Problemlöser. Um effizienten Code zu schreiben, müssen Entwickler Best Practices befolgen. PHP Design Patterns ist ein Konzept der objektorientierten Programmierung (OOP), das jetzt auch in Drupal 8-Projekten verwendet wird. Da Drupal 8 moderne PHP- und OOP-Konzepte übernimmt, können Designmuster für eine sauberere und robustere Programmierung genutzt werden.

Designmuster in PHP

Was sind Designmuster in PHP?

In der Softwareentwicklung ist ein Design Pattern eine allgemeine wiederholbare Lösung für häufig auftretende Probleme im Softwaredesign. Gute objektorientierte Designs sollten wiederverwendbar, wartbar und erweiterbar sein und Design Patterns in PHP könnten dabei sehr hilfreich sein. Es hilft nicht nur bei der Lösung von Problemen, sondern impliziert eine optimale Lösung gemeinsamer Herausforderungen.

Vorteile der Verwendung von PHP Design Patterns

Die wichtigsten Vorteile von Designmustern in PHP sind:

  • PHP-Designmuster helfen bei der Lösung sich wiederholender Probleme, die während der Entwicklung auftreten
  • Die Verwendung von Designmustern in PHP macht die Kommunikation zwischen Designern effizienter
  • Andere Entwickler, die sich Ihren Code ansehen, müssen sich nicht schwer tun, ihn zu verstehen, da der Code gut mit Designmustern strukturiert ist
  • Das Befolgen von Best Practices hilft bei der Entwicklung robusterer Software
  • Es hilft, die Entwicklung schneller und einfacher zu machen

Weit verbreitete Design Patterns in PHP

Design Patterns können in verschiedenen Situationen verwendet werden, um ähnliche Probleme zu lösen. Es gibt etwa 23 Designmuster, die grob in drei Arten von Designmustern kategorisiert werden können – Kreations-, Struktur- und Verhaltensmuster.

Erstellungsmuster: Entwurfsmuster, die in Objekterstellungsmechanismen verwendet werden, um Objekte zu erstellen, die von dem System, das sie implementiert hat, entkoppelt werden können.

Strukturmuster: Dies erleichtert das Design, indem einfache Wege identifiziert werden, um Beziehungen zwischen Entitäten zu realisieren

Verhaltensmuster: Sie werden verwendet, um Beziehungen, Verantwortlichkeiten und Algorithmen zwischen Objekten zu verwalten

Fabrikmuster

Ein Fabrikmuster wird verwendet, um ein Objekt zu erstellen. Das ist richtig – erstelle ein Objekt und erstelle kein Objekt. Wenn wir das Objekt erstellen, erstellen wir es zuerst und initialisieren es dann. Normalerweise ist es erforderlich, eine bestimmte Logik anzuwenden und mehrere Schritte auszuführen. Daher ist es sinnvoll, all dies an einem Ort zu haben und immer dann wiederzuverwenden, wenn Sie ein neues Objekt auf die gleiche Weise erstellen müssen. Im Grunde ist das die Verwendung des Fabrikmusters.
Es ist eine großartige Idee, eine Schnittstelle für unsere Fabrik zu haben und unseren Code davon abhängig zu machen und nicht von einer konkreten Fabrik

 Schnittstelle FamilyFactoryInterface {
    allgemein Funktion erstellen () : Familie
}

Implementieren Sie als Nächstes die Factory-Schnittstelle mit der folgenden Klasse:

Klasse FamilieFabrik implementiert FamilyFactoryInterface {

allgemein Funktion erstellen () : Familie {

$familie = neue Familie();

// initialisiere deine Familie

$familie zurückgeben;

}

}

Adaptermuster

Im Adapter Design Pattern transformiert eine Klasse die Schnittstelle einer Klasse in eine andere Klasse. In diesem Beispiel haben wir eine TextBook- Klasse, die über die Methoden getTitle() und getAuthor() verfügt. Der Client erwartet eine Methode getTitleAndAuthor(). Um SimpleBook für demoAdapter "anzupassen", haben wir eine Adapterklasse, BookAdapter , die eine Instanz von TextBook aufnimmt und die TextBook-Methoden getTitle() und getAuthor() in ihrer eigenen Methode getTitleAndAuthor verwendet.

<?php

Klasse Lehrbuch {

privater $titel;
privat $Autor;
Funktion __konstruieren ($title_in, $author_in) {
$this ->title = $title_in;

$this ->author = $author_in;
}

Funktion getTitle () {
Rückkehr $dies ->Titel;
}
Funktion getAuthor () {
Rückkehr $this ->Autor;
}
}

Klasse BuchAdapter {
privates $buch;
Funktion __construct (TextBook $book_in) {
$this ->book = $book_in;
}
Funktion getTitleAndAuthors () {
Rückkehr $this ->book->getTitle(). 'durch' . $this ->book->getAuthor();
}
}

// Klient

writeln( 'BEGIN TESTING ADAPTER PATTERN' );
schreiben ( '' );

$book = new TextBook( "Gamma, Helm, Johnson und Vlissides" , "Design Patterns" );
$bookAdapter = new BookAdapter($book);
writeln( 'Autor und Titel: ' .$bookAdapter->getTitleAndAuthor());
schreiben ( '' );

writeln( 'END TESTING ADAPTER PATTERN' );

Funktion writeln ($line_in) {
echo $line_in. "<br/>" ;
}

?>

PHP-Singleton-Muster

Um die Instanziierung einer Klasse auf ein einzelnes Objekt zu beschränken, wird in PHP ein Singleton-Muster verwendet. Dies kann nützlich sein, wenn im gesamten System nur ein Objekt benötigt wird. Es ist sinnvoll, beim Entwerfen von Webanwendungen nur den Zugriff auf eine Instanz einer bestimmten Klasse zuzulassen. Um die explizite Erstellung von Objekten aus der Singleton-Musterklasse zu verhindern, wird ein privater Konstruktor verwendet.

<?php
Klasse Singleton
{
allgemein statisch Funktion getInstance ()
{
statisch $Instanz = null ;
if ( null === $Instanz) {
$Instanz = neu statisch ();
}
return $ Instanz;
}
geschützt Funktion __konstruieren ()
{
}
Privatgelände Funktion __klon ()
{
}
Privatgelände Funktion __aufwachen ()
{
}
}
Klasse SingletonKind erweitert Singleton
{
}
$obj = Singleton::getInstance();
var_dump($obj === Singleton::getInstance());
$obj2 = SingletonChild::getInstance();
var_dump($obj2 === Singleton::getInstance());
var_dump($obj2 === SingletonChild::getInstance());
?>

Beobachtermuster in PHP

Das PHP-Observer-Muster wird verwendet, um den Rest des Systems über bestimmte Ereignisse an bestimmten Orten zu warnen.
Zum Beispiel, wenn wir ein Theater schaffen müssen, um den Kritikern Filme zu zeigen. Wir definieren die Klasse Theater mit der aktuellen Methode. Bevor der Film präsentiert wird, wollen wir Nachrichten auf die Handys der Kritiker schicken. Dann wollen wir mitten im Film den Film für 5 Minuten anhalten, damit die Kritiker eine Pause haben. Schließlich möchten wir die Kritiker nach dem Ende des Films bitten, ihre Antwort zu hinterlassen. Im Observer-Pattern für PHP wird das Observer-Objekt also nur benachrichtigt, wenn sich der Status ändert.

So sieht Code aus -

Klasse Theater {

allgemein Funktion aktuell (Film $movie) : void {

$critics = $movie->getCritics();
$this ->message->send($critics, '...' );

$movie->play();

$movie->pause( 5 );
$this ->Fortschritt ->Intervall($kritiker)
$movie->end();

$dies ->Antwort->Anfrage($Kritiker);
}
}

Decorator-Muster für PHP

Das Decorator-Muster wird verwendet, wenn Sie den Charakter eines Objekts zur Laufzeit ändern und damit unnötige Vererbungen und die Anzahl der Klassen reduzieren möchten. Nun, es kann mit Beispielen erklärt werden. Nehmen wir an, wir haben die Klassen Sofa und Bed, und beide implementieren SleeperInterface.

Schnittstelle SleeprInterface {
allgemein Funktion schlafen () : leer;
}
Klasse Sofa implementiert SleeperInterface {
allgemein Funktion Schlaf () : Leere {
// schläft auf dem Sofa
}
}
Klasse Bett implementiert SleeperInterface {
allgemein Funktion Schlaf () : Leere {
// schläft im Bett
}
}

Sowohl die Sofas als auch die Betten haben das gleiche Schlafverhalten. Jetzt brauchen wir andere Sofas und Betten mit zusätzlichen Funktionen, die den Benutzern das Schlaftracking mitteilen, wenn sie auf den Sofas oder Betten schlafen. Mit Vererbung können wir dieses Problem einfach so lösen:

Klasse SmartSofa erweitert Sofa {
öffentliche Funktion sleep() : void {
parent::sleep();
$ this ->sleepHours();
}
}
Klasse SmartBed erweitert Fenster {
öffentliche Funktion sleep() : void {
parent::sleep();
$ this ->sleepHours();
}
}

Jetzt haben wir insgesamt 4 Klassen. Allerdings konnten wir dieses Problem mit 3 Klassen nur mit dem Decorator-Muster lösen. Hier ist wie:

Klasse SmartSleeper implementiert SleeperInterface {

privater Schlafplatz;
allgemein Funktion __construct (SleeperInterface $sleeper) {
$dieser ->Schläfer = $Schläfer;
}

allgemein Funktion Schlaf () : Leere {
$this ->Schlaf->Schlaf();
$this ->sleepHours();
}
}
$sofa = neues Sofa();
$bed = neues Bett();
$smartSofa = neuer SmartSleeper($sofa);
$smartBed = neuer SmartSleeper($bed);

Hier haben wir einen neuen Schläfertyp eingeführt, der sich wie ein Proxy verhält, aber darüber hinaus eine zusätzliche Funktionalität bietet.

Nutzung von Designmustern in Drupal 8

Während vor Drupal 8 bereits viele Designmuster in Drupal etabliert wurden, besteht Drupal 8 jetzt aus vielen Mustern, die zuvor nicht verfügbar waren. Einige dieser neuen Muster ersetzen einige ältere vollständig, während andere einige neue Funktionen in Drupal 8 einführen.

Die in Drupal 8 verwendeten Designmuster umfassen:

  • Objektorientiertes Programmiermuster (OOP)
  • Abhängigkeitsinjektionen
  • Fabrikmuster
  • Singleton-Muster

OOP ist nicht wirklich ein einzelnes Muster, sondern eine völlig radikale Art, Codes zu konzeptualisieren und zu strukturieren, die weit über reine Designmuster hinausgeht. Es ist die Grundlage für viele gängige Software-Designmuster, die heute verwendet werden, einschließlich derjenigen, die in Drupal 8 verwendet werden. Es wurde in Drupal 7 eingeführt, wurde jedoch nicht ausgiebig verwendet und war nicht erforderlich. Die Situation in Drupal 8 ist jetzt anders, es wird weit verbreitet und benötigt.

Abhängigkeitsspritze

Dependency Injection ist ein Software-Entwurfsmuster, mit dem Sie hartcodierte Abhängigkeiten entfernen und sie entweder zur Laufzeit oder zur Kompilierzeit ändern können. Das Hinzufügen von Dependency Injection ist einfach und mischt sich nicht in Ihren vorhandenen Code ein. Drupal 8 führte das Konzept der Dienste ein, um die wiederverwendbaren Funktionalitäten zu entkoppeln. core.services.yml ist ein Beispiel für Dependency Injection in Drupal 8. Wir haben oben bereits über Factory Pattern und Singleton Pattern in PHP gesprochen