cybton.com
Über uns | Jobs | Werbung | Sitemap | AGB | Impressum | Hilfe ?
 Kostenlos anmelden)
wichtigWir suchen PHP-Entwickler/innen (Freelancer oder Vollzeit)
eBooks
Hochgeladene Bilder
Letzte Änderungen

Lexikon

Bücher
Themengebiete

Tutorials


Statistik
Mitglieder gesamt: 69388
Mitglieder online: 1
Gäste online: 5
mehr...

Anzeige
eBooks » eBook: PHP » eBook Kapitel: Entwurfsmuster

eBook Kapitel: Entwurfsmuster

Inhaltsverzeichnis

Einführung

Fortlaufendes Beispiel

Als fortlaufendes, "wissenschaftliches" Beispiel wird hier für den Informatiker eine kleine Welt geschaffen, in dem er sich wohlfühlen und austoben kann. In diesem Beispiel werden die aufgeführten Entwurfsmuster in einem anschaulichen Zusammenhang verwendet.
Letzte Änderung: 14.05.2009 16:41 Uhr

Singleton

Erläuterung

Bei dem Singleton-Entwurfsmuster handelt es sich um ein erzeugendes Muster. Hierbei wird dafür gesorgt, dass nur eine Instanz einer Klasse existieren kann. Um dies zu erreichen werden Konstruktor und Methoden zum Klonen als private oder protected gekennzeichnet. Die Instanziierung der Klasse erfolgt durch einen Methodenaufruf. Allgemein wird als Methodenname singleton oder getInstance verwendet.

UML

[...]

PHP-Implementierung

+ PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class EinfacheSingletonKlasse {
   static private $_instance;
 
   protected function __construct() {
      //...
   }
 
   protected function __clone() {
   }
 
   static public function singleton() {
      if (! self::$_instance instanceof self) {
         self::$_instance = new self();
      }
      return self::$_instance;
   }
}

Fortlaufendes Beispiel

Basis der Informatikerwelt bildet ein Gott. Wie allgemein bekannt gibt es genau einen Gott, wodurch sich für Ihn das Singleton-Pattern anbietet. Eine einfache Implementierung von Gott könnte also so (oder ähnlich) aussehen:
+ PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
// god.php
// required php5.0
 
class God {
   // stellt singleton pattern bereit; hält eine Instanz der God-Klasse
   static private $_instance;
 
   // stellt singleton pattern bereit
   protected function __construct() {
   }
 
   // stellt singleton pattern bereit
   protected function __clone() {
   }
 
   // stellt singleton pattern bereit
   static public function singleton() {
      if (! self::$_instance instanceof self) {
         self::$_instance = new self();
      }
      return self::$_instance;
   }
 
   public function isAlmighty() {
      return true;
   }
 
   // TODO: other code here
}
Letzte Änderung: 14.05.2009 16:40 Uhr

Factory

Erläuterung

Die Abstract-Factory ist ein erzeugendes Entwurfsmuster. Hier wird mit Hilfe von zwei abstrakten Klassen sowohl ein Produkt als auch eine Fabrik abgebildet, die anschließend als konkrete Fabrik oder konkretes Produkt implementiert werden. Durch Aufruf einer Methode innerhalb der Fabrik werden neue Instanzen der Produkt-Klasse erzeugt und zurückgegeben. Eine Abstract-Factory hat also gewisse Ähnlichkeit mit anderen erzeugenden Entwurfsmustern, wie beispielsweise dem Singleton-Pattern.

UML

[...]

PHP-Implementierung

+ PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
abstract class Product() {
   //...
}
 
class MyProduct extends Product() {
   //...
}
 
abstract class Factory {
  abstract public function createProduct(); // Factory-Methode
}
 
class MyFactory extends Factory {
   public function createProduct() {
      return new MyProduct();
   }
}

Fortlaufendes Beispiel

Das wichtigste Produkt für den Informatiker ist natürlich der Kaffee. Entsprechend gibt es eine beliebige Anzahl an Replikatoren, die eine Tasse Kaffe erzeugen und ausgeben können.
Zunächst werden also die Abstrakten Klassen der Abstract Factory erstellt.
PHP:
1
2
3
4
5
<?php
// required: php5.3
// file: product.php
abstract class Product {
}
PHP:
1
2
3
4
5
6
<?php
// required: php5.3
// file: factory.php
abstract class Factory {
   //...
}
Diese werden nun als Produkt und reale Factory-Implementierung abgebildet. Für spätere Zwecke erhält das Produkt einige zusätzliche Methoden zum leeren des Füllstandes und zum Prüfen, ob es leer ist.
+ PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// required: php5.3
// file: cupofcoffee.php
require_once 'product.php';
 
class CupOfCoffee extends Product {
   private $_fillingLevel = 1;
 
   public function __construct() {
   }
 
   public function reduceFillingLevel() {
      if (! $this->isEmpty()) {
         $this->_fillingLevel = $this->_fillinglevel - 0.2;
      } else {
         throw new Exception('The cup is empty');
      }
   }
 
   public function isEmpty() {
      return $this->_fillingLevel <= 0;
   }
}
Abschließend wird nun die Replikatorklasse erstellt. Dieser Replikator kann nur neue Kaffeetassen erzeugen.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
// required: php5.3
// file: replicator.php
require_once 'factory.php';
require_once 'cupofcoffee.php';
 
class Replikator extends Factory {
   // stellt abstract-factory pattern
   public function createCupOfCoffee() {
      return new CupOfCoffee();
   }
}
Die Verwendung ist denkbar einfach. Es wird die Instanz eines Replikators erzeugt und auf diesem bei Bedarf Methoden zur Erzeugung von Produkten aufgerufen. Die entsprechende Methode gibt nun ein Produkt zurück, das wie gewohnt verwendet werden kann.
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?php
// required: php5.3
// file: test_replicator.php
require_once 'replicator.php';
$replicator = new Replicator();
$cup = $replicator->createCupOfCoffee();
try {
   $cup->reduceFillingLevel();
} catch(Exception $e) {
   echo $e->getMessage();
}
Letzte Änderung: 14.05.2009 17:29 Uhr

Prototype

[Noch kein Text vorhanden]

Adapter

Ziel dieses Musters ist eine eigene Schnittstelle zu einer bereits vorhandenen Schnittstelle zu erstellen,
wenn die ursprüngliche Schnittstelle nicht kompatibel war.

ursprüngliche Schnittstelle
php:
1
2
3
4
5
6
7
8
9
10
 
<?php
class wirbelsaeulentier {
      public function open_maul(){}
      public function close_maul(){}
      public function kauen($things){}
      public function schnlucken(){}
 
}
?>
unsere Schnittstelle braucht aber folgende Methode
php:
1
2
3
4
5
<?php
class wirbelsaeulentier {
      public function eat($things){}
}
?>
Somit kommt das Adapter-Pattern zur Anwendung
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class wirbelsaeulentierAdapter(){
 
      protected $wirbelsaeulentier = NULL;
 
      public function __construct($wirbelsaeulentier){
            $this->wirbelsaeulentier = $wirbelsaeulentier;
      }
      public function eat($things){
            try{
                  $this->wirbelsaeulentier->open_maul();
                  $this->wirbelsaeulentier->kauen($things);
                  $this->wirbelsaeulentier->schlucken();
                  $this->wirbelsaeulentier->close_maul();
            }catch(FrameworkException $e){
                  return false;
            }
            return true;
      }
 
}
?>
Letzte Änderung: 13.05.2009 20:22 Uhr

Bridge

[Noch kein Text vorhanden]

Composite

Eine Webanwendung besteht meistens aus mehreren Klassen. Wenn aber nicht jede Klasse nach außen sichtbar sein soll (information hidding), wird das Kompositum angewendet. Bei diesem Muster werden mehrere Objekte zu einem Objekt zusammen gefasst.

PHP Implementierung
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class LebewesenComposite{
  protected $Lebewesen = array();
  
  public function addLebewesen(Lebewesen_interface $Lebewesen){
              $this->Lebewesen[] = $Lebewesen;
  }
  
  public function eat($things){
        foreach ($this->Lebewesen as $Lebewesen_item){
            $Lebewesen_item->eat($things);
      }
  }
  public function drink($liter){
        foreach ($this->Lebewesen as $Lebewesen_item){
            $Lebewesen_item->drink($liter);
      }
  }
}
?>
Interface
php:
1
2
3
4
5
6
7
8
<?php
interface Lebewesen_interface{
      //  ...
      // spezielle Methoden, die alle Lebewesen haben müssen
      public function eat($things);
      public function drink($liter);
}
?>
komplette Anwendung
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
class wirbelsaeulentier implements Lebewesen_interface{
      public function eat($things){}
      public function drink($liter){
            if($liter < 3){
                  // verdursten
            }
      }
 
}
class weichtier implements{
      public function eat($things){}
      public function drink($liter){
            if($liter > 0.001){
                  // zerplatzen
            }
      }
 
}
 
 
$stier = new wirbelsaeulentier();
$mensch = new wirbelsaeulentier();
$regenwurm = new weichtier();
 
$welt = new LebewesenComposite();
$welt->addLebewesen($stier);
$welt->addLebewesen($mensch);
$welt->addLebewesen($regenwurm);
?>
Letzte Änderung: 13.05.2009 20:23 Uhr

Decorator

Bestehende Klassen können nicht mehr durch extends zur Laufzeit erweitert werden. Mit dem Dekorierer ist dies nun möglich.
php:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
class sprinter{
      protected $max_speed;
      
      public function __construct($speed = 100){
            $this->max_speed = $speed;
      }
      public function get_max_speed(){
            return $this->max_speed;
      }
}
?>
Was aber nun, wenn dem Sprinter Spikes zur Verfügung stehen?
php:
1
2
3
4
5
<?php
interface ausruestung{
      public function get_additionalspeed();
}
?>
php:
1
2
3
4
5
6
7
<?php
class spikes implements ausruestung{
      public function get_additionalspeed(){
            return 10;
      }
}
?>
Jetzt müssen wir nur noch die vorhande Klasse überarbeiten.
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class sprinter{
      protected $max_speed;
      protected $extra = array();
      
      public function __construct($speed = 100){
            $this->max_speed = $speed;
      }
      public function get_max_speed(){
                  $speed = $this->max_speed
            foreach($this->extra as $extra){
                  $speed = $speed + $extra->get_additionalspeed();
            }
            return $speed;
      }
      
      public function addExtra(ausruestung $extra){
            $this->extra[] = $extra;
      }
}
?>
Nun schauen wir mal wie schnell unserer Läufer ist:
php:
1
2
3
4
5
6
7
8
<?php
$alfred = new sprinter();
echo "Alfred hat keine Spikes an und läuft so schnell: ".$alfred->get_max_speed()."<br/>";
echo "Alfred zieht seine Spikes nun an..."."<br/>";
$spikes = new spikes();
$alfred->addExtra($spikes);
echo "Alfred hat nun Spikes an und läuft so schnell: ".$alfred->get_max_speed()."<br/>";
?>
Ausgabe:
diff:
1
2
3
4
 
Alfred hat keine Spikes an und läuft so schnell: 100
Alfred zieht seine Spikes nun an...
Alfred hat nun Spikes an und läuft so schnell: 110
Jetzt lassen wir ihn noch richtige Sprinterkleidung anziehen:
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class spikes implements ausruestung{
      public function get_additionalspeed(){
            return 10;
      }
}
class hose implements ausruestung{
      public function get_additionalspeed(){
            return 2;
      }
}
 
$alfred = new sprinter();
echo "Alfred hat keine Spikes an und läuft so schnell: ".$alfred->get_max_speed()."<br/>";
echo "Alfred zieht seine Spikes nun an..."."<br/>";
$spikes = new spikes();
$alfred->addExtra($spikes);
echo "Alfred hat nun Spikes an und läuft so schnell: ".$alfred->get_max_speed()."<br/>";
echo "Alfred zieht seine Sprinterkleidung nun an..."."<br/>";
$hose = new hose();
$alfred->addExtra($hose);
echo "Alfred hat nun eine andere Hose an und läuft so schnell: ".$alfred->get_max_speed()."<br/>";
?>
Letzte Änderung: 14.05.2009 12:43 Uhr

Proxy

Dieses Muster erzeugt einen Stellvertreter für ein Objekt um den Zugriff zu überwachen.
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class sprinter implements Lebewesen_interface{
      protected $max_speed;
      protected $extra = array();
      
      public function __construct($speed = 100){
            $this->max_speed = $speed;
      }
      public function get_max_speed(){
                  $speed = $this->max_speed
            foreach($this->extra as $extra){
                  $speed = $speed + $extra->get_additionalspeed();
            }
            return $speed;
      }
      
      public function addExtra(ausruestung $extra){
            $this->extra[] = $extra;
      }
      public function eat($things){}
      public function drink($liter){}
}
?>
Jetzt wollen wir wissen, ob unser Alfred als Sportler dopt.
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
class sprinter_proxy implements Lebewesen_interface{
      protected $max_speed = 100;
      protected $extra = array();
      
      public function __construct($original){
            $this->instance = $original;
      }
      public function get_max_speed(){
            return $this->instance->get_max_speed();
      }
      
      public function addExtra(ausruestung $extra){
            return $this->instance->addExtra(ausruestung $extra);
      }
      public function eat($things){
            // Dopingkontrolle
            if($things == "Doping"){
                  throw new Dopingexception("Sportler nimmt Dopingmittel.");
            }else{
                  return $this->instance->eat($things);
            }
      }
      public function drink($liter){
            return $this->instance->drink($liter);
      }
}
?>
komplette Anwendung:
php:
1
2
3
4
5
6
7
8
9
10
11
 
<?php
$alfred   = new sprinter();
// noch darf er dopen...
$alfred->eat('Doping');
// jetzt nicht mehr
$alfred_p = new sprinter_proxy($alfred);
$alfred_p->eat('Doping'); // verursacht Fehler (Exception)
 
 
?>
Letzte Änderung: 14.05.2009 12:41 Uhr

Facade

[Noch kein Text vorhanden]

Chain of Responsibility

[Noch kein Text vorhanden]

Iterator

Elemente eines Objektes können durch dieses Muster sequenziell angesprochen werden.

PHP(Version 5) bringt standardmäßig schon eine Implementierung dieses Musters mit:

Interface vom Iterator-Pattern:
php:
1
2
3
4
5
6
7
8
9
10
11
<?php
 
interface Iterator{
      public function key();
      public function next();
      public function rewind();
      public function valid();
      public function current();
      
}
?>
Jetzt wollen wir ein ganzes Startfeld von Sprinter darstellen.
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class startfeld{
      private $sprinter = array();
 
      public function __construct($csv){
            // CSV mit Daten einlesen und immer eine eigene Instance der Klass "sprinter" erzeugen
      }
      public function countSprinter(){
            return count($this->sprinter);
      }
      public function getSprinter($pos){
            if($pos>=$this->countSprinter()){
                  // FEHLER Zeiger außerhalb Liste
            }else{
                  return $this->sprinter[$pos];
            }
            
      }
      
 
}
?>
Um das Startfeld auszugeben würde folgender Code verwendet:<br />
php:
1
2
3
4
5
6
7
8
<?php
 
$teilnehmer = new startfeld("export.csv");
for($i=0; $i < $teilnehmer->counterSprinter();$i++){
      $sprinter = $teilnehmer->getSprinter($i);
      echo $sprinter->getName();
}
?>
Jetzt kommt das Pattern zum Einsatzt
+ php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
class startfeld implements Iterator{
      private $sprinter = array();
      private $pos = 0;
 
      public function __construct($csv){
            // CSV mit Daten einlesen und immer eine eigene Instance der Klass "sprinter" erzeugen
      }
      public function countSprinter(){
            return count($this->sprinter);
      }
      public function getSprinter($pos){
            if($pos>=$this->countSprinter()){
                  // FEHLER Zeiger außerhalb Liste
            }else{
                  return $this->sprinter[$pos];
            }
            
      }
      // neue Iteratormethoden
      public function key(){
            return $this->pos;
      }
      public function next(){
            $this->pos++;
      }
      public function rewind(){
            $this->pos = 0;
      }
      public function valid(){
            if($this->pos < $this->countSprinter()){
                  return true;
            }
            return false;
      }
      public function current(){
            return $this->sprinter[$pos];
      }
}
?>
Somit kann die Ausgabe so geschrieben werden, dass dieselbige nur Methoden verwendet, die vom Iteratorpatter vorausgesetzt werden.
php:
1
2
3
4
5
6
7
8
9
10
<?php
$teilnehmer = new startfeld("export.csv");
while($teilnehmer->valid()){
      $pos             = $teilnehmer->key();
      $sprinter      = $teilnehmer->current();
      echo "Sprinter mit der Nummer {$pos} heißt {$sprinter->getName()}";
      $teilnehmer->next();
 
}
?>
Oder mit Foreach:
php:
1
2
3
4
5
6
<?php
$teilnehmer = new startfeld("export.csv");
foreach($teilnehmer as $i => $sprinter){
      echo "Sprinter mit der Nummer {$pos} heißt {$sprinter->getName()}";
}
?>
Letzte Änderung: 13.05.2009 20:25 Uhr

Observer

Die genau Bezeichnung sollte Subject/Observer heißen. Ein Subjekt (subject) besitzt viele Abhängigkeiten(Verbindungen) zu beliebig vielen externen Beobachtern. Diese werden bei Zustandsänderungen des Subjektes informiert.
Letzte Änderung: 13.05.2009 20:26 Uhr

Visitor

[Noch kein Text vorhanden]

Plugin

[Noch kein Text vorhanden]

Inversion of Control

[Noch kein Text vorhanden]

Active-Record

Ähnelt sehr stark dem Row Data Gateway Pattern. Genau genommen beinhaltet es dieses, fügt aber noch weitere Logik dem Objekt hinzu.
Letzte Änderung: 13.05.2009 20:26 Uhr

Row Data Gateway

Dieses Pattern wird als Repräsentation einer Zeile von einer Datenbanktablle verwendet. Eine Instanz beschreibt eine Zeile. Mit Propel kann man solche Klassen automatisch erzeugen.
Letzte Änderung: 13.05.2009 20:26 Uhr

Statemachine

[Noch kein Text vorhanden]

MVC

Dieses Pattern ist genau genommen ein Zusammenschluss mehrerer Muster. Mit dem MVC können Schichten in einer Webanwendung getrennt werden.
Die Abkürzung steht für.
  • Model: speichert Daten und kann dem View über Datenänderungen informieren
  • View: stellt Daten dar und kann Daten beim Model abfragen
  • Controller: nimmt Interaktionen mit dem Besucher auf und gibt Anweisungen an Model und View weiter.
Letzte Änderung: 31.05.2009 21:57 Uhr

HMVC

[Noch kein Text vorhanden]

PAC

[Noch kein Text vorhanden]

Diskussion

Zum Diskussions Thread [10 Beiträge]
nach obennach oben

Copyright © 2014 cybton-network

Google
Partner: #Musik - Dein Internetradio - nexem. - .wir machen news
ANEXIA - PHP Entwicklung - Web-Entwicklung - Fritz!Box Anrufmonitor für Mac OS - Rolladen, Markisen und Jalousien in Stuttgart - Rolladen in Stuttgart - SMSjobs