<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ebene7 &#187; Design Patterns</title>
	<atom:link href="http://blog.ebene7.com/schlagwort/design-patterns/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ebene7.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 Jun 2013 18:57:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>&#8220;Walkable&#8221; Iterator</title>
		<link>https://blog.ebene7.com/2012/07/31/walkable-iterator/</link>
		<comments>https://blog.ebene7.com/2012/07/31/walkable-iterator/#comments</comments>
		<pubDate>Tue, 31 Jul 2012 04:00:00 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[each]]></category>
		<category><![CDATA[Foreach]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[Schleife]]></category>
		<category><![CDATA[Visitor Pattern]]></category>
		<category><![CDATA[walk]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3499</guid>
		<description><![CDATA[In PHP haben Entwickler seit Version 5 die Möglichkeit, den Zugriff auf Datenstrukturen durch eigene oder bereits in der SPL vorhandene Iteratoren zu kontrollieren. Das ist einfach und hat sicherlich auch schon jeder einmal gemacht. Damit ist dann zumindest der &#8230; <a href="https://blog.ebene7.com/2012/07/31/walkable-iterator/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In PHP haben Entwickler seit Version 5 die Möglichkeit, den Zugriff auf Datenstrukturen durch eigene oder bereits in der <a href="http://www.php.net/~helly/php/ext/spl/" target="_blank">SPL</a> vorhandene <a href="http://blog.ebene7.com/schlagwort/iterator/">Iteratoren</a> zu kontrollieren. Das ist einfach und hat sicherlich auch schon jeder einmal gemacht.</p>
<p>Damit ist dann zumindest der eine Teil, die Datenstruktur, für sich gekapselt. Was ist aber mit dem Teil, den wir wahrscheinlich häufiger verwenden werden? Wir nutzen Iteratoren in Schleifen und machen irgendwas mit den Elementen.<span id="more-3499"></span></p>
<pre>&lt;?php
foreach($list as $key =&gt; $item) {
  $item-&gt;doSomething();
}

// oder
$values = array();
foreach($list as $key =&gt; $item) {
  $values[] = $item-&gt;getSomething();
}</pre>
<p>In verschiedenen anderen Sprachen, Java, JavaScript etc., sieht man häufig, dass dort auch die Scheifen gekapselt sind. Warum probieren wir das nicht auch mal in PHP?</p>
<p>Ich werde das Beipiel bewusst einfach halten und wie gewohnt auf einige Fehlerbehandlungen verzichten, um den Code übersichtlich zu halten.</p>
<p>Als erstes erstellen wir eine Klasse &#8220;WalkableIterator&#8221; und lassen diese von ArrayIterator erben. Die beiden Methoden &#8220;each&#8221; und &#8220;walk&#8221; bilden später unsere beiden Beispiele ab.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  public function each($method) {}
  public function walk($callback) {}
}</pre>
<p>Mit each() können wir eine bestimmte Methode auf jedem Element in unserem Iterator aufrufen. Dafür müssten hier natürlich diverse Fehlerbehandlungen rein was passieren soll, wenn das Element kein Objekt ist oder die Methode nicht existiert oder diese gar eine Exception wirft.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  public function each($method) {
    $args = func_get_args();
    $method = array_shift($args);
    foreach($this as $item) {
      call_user_func_array( array($item, $method), $args );
    }
  }
  // ...
}</pre>
<p>Das ganze ist denkbar einfach: Die Methode nimmt als ersten Pflichtparameter den Methodennamen entgegen, die auf allen Elementen aufgerufen werden soll und der Rest bleibt flexibel und wird einfach nur durchgereicht.</p>
<p>Die Implementierung von walk() wird sogar noch einfacher, da hier keine Parameter weitergegeben werden müssen. Im produktiven Einsatz müssten auch hier noch die üblichen Fehlerbehandlungen rein.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  // ...
  public function walk($callback) {
    foreach($this as $item) {
      call_user_func( $callback, $item );
    }
  }
}</pre>
<p>Soweit, so einfach&#8230; Was können wir jetzt damit machen? Bauen wir ein kleines Beispiel.</p>
<pre>&lt;?php
// Testklasse
class Person {
  private $name;
  public function __construct($name = 'unnamed') {
    $this-&gt;setName($name);
  }
  public function getName() {
    return $this-&gt;name;
  }
  public function setName($name) {
    $this-&gt;name = $name;
  }
}

// Testarray mit Objekten befüllen
$a = array();
for($i=1; $i &lt;= 10; $i++) {
  $a[] = new Person('Person ' . $i);
}

// Iterator erstellen und Namen ausgeben
$it = new WalkableIterator($a);

foreach($it as $item) {
  echo $item-&gt;getName() . '&lt;br/&gt;';
}

// Person 1
// ...
// Person 10</pre>
<p>Wollten wir nun allen Personenobjekten einen Namen geben, so könnten wir dafür each() verwenden.</p>
<pre>&lt;?php
$it-&gt;each('setName', 'PHP-Nerd');

// PHP-Nerd
// ...
// PHP-Nerd</pre>
<p>Wollen wir unsere Personen dann vielleicht doch wieder individueller benennen, so könnten wird das mit walk() und einem <a href="http://blog.ebene7.com/schlagwort/callback/">Callback</a> machen.</p>
<pre>$callback = function(Person $person) {
  static $count = 1;
  $person-&gt;setName( $person-&gt;getName() . ' ' . $count++ );
};

$it-&gt;walk($callback);</pre>
<pre>// PHP-Nerd 1
// ...
// PHP-Nerd 10</pre>
<p>&#8220;Was bringt uns das und warum so kompliziert?&#8221;, ist in dem Zusammenhang eine oft gehörte Frage.</p>
<p>Zunächst ist die Implementierung, wie das Beispiel sicher beweist, nicht kompliziert.</p>
<p>Die Vorteile sind kürzere Aufrufe im Code, weil wir keine Schleifen mehr schreiben müssen und durch die Kapselung verbessert sich auch die Wart- und Testbarkeit. Der Code existiert nur an einer Stelle und funktioniert überall nach dem selben Muster.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2012/07/31/walkable-iterator/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TemplateMethod vs. method_exists()-Prüfung</title>
		<link>https://blog.ebene7.com/2012/01/11/templatemethod-vs-method-exists-pruefung/</link>
		<comments>https://blog.ebene7.com/2012/01/11/templatemethod-vs-method-exists-pruefung/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 07:00:07 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[Benchmark]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Template Method]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3295</guid>
		<description><![CDATA[Das Entwurfsmuster TemplateMethod kennen und nutzen sicherlich viele von euch. Spätestens, wenn irgendein Framework im Einsatz ist, hat man in der Regel damit zu tun, um z.B. an verschiedenen Stellen im Code eigene Funktionen in einen Ablauf einzuhängen. Das Prinzip &#8230; <a href="https://blog.ebene7.com/2012/01/11/templatemethod-vs-method-exists-pruefung/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Das Entwurfsmuster <a href="http://de.wikipedia.org/wiki/Template_Method" target="_blank">TemplateMethod</a> kennen und nutzen sicherlich viele von euch. Spätestens, wenn irgendein Framework im Einsatz ist, hat man in der Regel damit zu tun, um z.B. an verschiedenen Stellen im Code eigene Funktionen in einen Ablauf einzuhängen.<span id="more-3295"></span></p>
<p>Das Prinzip ist einfach: in der (abstrakten) Basisklasse wird eine leere Methode definiert, die durch eine konkrete Klasse überschrieben werden kann.</p>
<p>Der Vorteil ist recht offensichtlich. Die Methode kann ohne vorherige Prüfung verwendet werden und das spart an vielen Stellen unnötigen Code. Aus meinem ästhetischem Empfinden der richtige Weg.</p>
<p>Aber auch den anderen Weg habe ich auch schon desöfteren gesehen und mein Bauchgefühl hat ja auch nicht immer recht. Vielleicht ist der schöne Weg ja auch der langsamere?</p>
<p>Gefühl ist gut, Zahlen sind besser! Also habe ich schnell drei Testklassen geschrieben und probiere die verschiedenen Möglichkeiten durch.</p>
<p>Variante 1: Wir verlassen uns darauf, dass die Methode aufgerufen werden kann.</p>
<pre>&lt;?php
class Test1 {
    public function machWas() {
        $this-&gt;machWasAnderes();
    }

    public function machWasAnderes() {
    }
}</pre>
<p>Variante 2: Wir prüfen, ob die Methode existiert und finden nichts.</p>
<pre>&lt;?php
class Test2 {
    public function machWas() {
        if (method_exists($this, 'machWasAnderes')) {
            $this-&gt;machWasAnderes();
        }
    }
}</pre>
<p>Variante 3: Wir prüfen, ob die Methode existiert und rufen sie auf.</p>
<pre>&lt;?php
class Test3 {
    public function machWas() {
        if (method_exists($this, 'machWasAnderes')) {
            $this-&gt;machWasAnderes();
        }
    }

    public function machWasAnderes() {
    }
}</pre>
<p>Zum Vergleich habe ich das folgende Script verwendet.</p>
<pre>&lt;?php
foreach (array('Test1', 'Test2', 'Test3') as $class) {
    $object = new $class();
    $start = microtime(true);

    for($i=0; $i&lt;100000; $i++) {
        $object-&gt;machWas();
    }
    echo $class . ' = ' . round(microtime(true) - $start, 5) . '&lt;br/&gt;';
}</pre>
<p>Ausgabe:</p>
<pre>Test1 = 0.44767
Test2 = 0.48588
Test3 = 0.70881</pre>
<p>In mehreren Durchläufen waren &#8220;Test1&#8243; und &#8220;Test2&#8243; immer fast gleich auf, nur &#8220;Test3&#8243; brauchte etwas länger, weil in der Klasse die Prüfung und die Ausführung der Methode stattfindet.</p>
<p>Fazit: Der Einsatz von Schablonenmethoden lohnt sich doppelt, da der Code übersichtlich bleibt und auch die Geschwindigkeit etwas besser ist.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2012/01/11/templatemethod-vs-method-exists-pruefung/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fluently self-contained Factory Method</title>
		<link>https://blog.ebene7.com/2010/09/29/fluently-self-contained-factory-method/</link>
		<comments>https://blog.ebene7.com/2010/09/29/fluently-self-contained-factory-method/#comments</comments>
		<pubDate>Wed, 29 Sep 2010 05:00:02 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Grundlagen]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Factory]]></category>
		<category><![CDATA[Singleton Pattern]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1510</guid>
		<description><![CDATA[Nein, wir spielen nicht Buzzword-Bingo. Heute geht es darum, Objekt-Instanzen durch einfache Factory Methoden zu erzeugen und sie im Weiteren als Fluent Interface direkt zu nutzen, ohne den Stolperstein &#8220;new&#8221; und ob das in der Form überhaupt sinnvoll ist. Der &#8230; <a href="https://blog.ebene7.com/2010/09/29/fluently-self-contained-factory-method/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Nein, wir spielen nicht Buzzword-Bingo. Heute geht es darum, Objekt-Instanzen durch einfache Factory Methoden zu erzeugen und sie im Weiteren als Fluent Interface direkt zu nutzen, ohne den Stolperstein &#8220;new&#8221; und ob das in der Form überhaupt sinnvoll ist.</p>
<p><span id="more-1510"></span>Der herkömmliche Weg eine Instanz einer Klasse zu erzeugen ist die Verwendung des new-Operators.</p>
<pre>&lt;?php
$meinObject = new MeineKlasse();
$meineKlasse-&gt;machWas();</pre>
<p>Leider funktioniert Methodenverkettung in PHP nicht wie in Java direkt nach &#8220;new&#8221; und wir müssen uns mit einer statischen Methode behelfen. Das Prinzip ähnelt dem Singleton-Muster, jedoch wollen wir in diesem Fall bei jedem Aufruf eine neue Instanz bekommen. Wer schonmal mit (Borland-)Delphi gearbeitet hat, der kennt das sicher schon.</p>
<pre>&lt;?php
class MeineKlasse
{
  public static function create()
  {
    return new self();
  }
}</pre>
<p>Der Vorteil ist nun ganz klar der, dass sich Instanzen in einer Zeile benutzen lassen.</p>
<pre>&lt;?php
MeineKlasse::create()-&gt;machWas();</pre>
<p>Leider fallen mir aber auch spontan zwei Nachteile ein: Bis PHP 5.3 ist die Methode nicht vererbbar, das bedeutet, dass wir die Methode mit jeder Ableitung erneut überschreiben müssten. Ab Version 5.3 kann statt &#8220;self&#8221; dann &#8220;static&#8221; instanziiert werden. Genaueres findet sich auch in den Links in meinem <a href="http://blog.ebene7.com/2010/08/30/vererbbares-singleton-pattern-dank-late-static-binding-ab-php-5-3/">Singleton-Artikel</a>.</p>
<p>Der zweite Nachteil ist genau der, warum man auch &#8220;new&#8221; nicht verwenden sollte. Beides schafft an vielen Stellen im Code Abhängigkeitet zu einer bestimmten Klasse. Wenn nun irgendwann eine abgeleitete Klasse benötigt wird müssen viele Änderungen gemacht werden.</p>
<p>Im Zweifelsfall sollte auf eine klassische, externe Factory zurückgegriffen werden, um derartigen Problemen im Voraus aus dem Weg zu gehen.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/09/29/fluently-self-contained-factory-method/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Vererbbares Singleton-Pattern dank Late Static Binding ab PHP 5.3</title>
		<link>https://blog.ebene7.com/2010/08/30/vererbbares-singleton-pattern-dank-late-static-binding-ab-php-5-3/</link>
		<comments>https://blog.ebene7.com/2010/08/30/vererbbares-singleton-pattern-dank-late-static-binding-ab-php-5-3/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 05:00:54 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Late Static Binding]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Singleton Pattern]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1310</guid>
		<description><![CDATA[Ob man das Singleton-Pattern nun mag oder nicht, es ist einfach in gewissen Situationen recht handlich und aus meiner Sicht auch nicht wirklich so böse wie es oft dargestellt wird, vorausgesetzt natürlich man weiß was man tut. Wirklich störend war &#8230; <a href="https://blog.ebene7.com/2010/08/30/vererbbares-singleton-pattern-dank-late-static-binding-ab-php-5-3/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ob man das Singleton-Pattern nun mag oder nicht, es ist einfach in gewissen Situationen recht handlich und aus meiner Sicht auch nicht wirklich so böse wie es oft dargestellt wird, vorausgesetzt natürlich man weiß was man tut.</p>
<p>Wirklich störend war aus meiner Sicht bislang nur, dass sich das Singleton nicht vererben ließ. Dank <a href="http://php.net/manual/de/language.oop5.late-static-bindings.php" target="_blank">Late Static Binding</a> seit PHP Version 5.3 ist nun auch das möglich.</p>
<p>Dazu habe ich vor ein paar Tagen einen guten <a href="http://blog.gi-project.de/2010/08/singleton-dank-late-static-binding-vererbbar/" target="_blank">Artikel von Julian</a> gefunden und auch noch einen englischsprachigen im <a href="http://www.brandonsavage.net/a-lesson-in-static-methods-and-late-static-binding/" target="_blank">Blog von Brandon</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/08/30/vererbbares-singleton-pattern-dank-late-static-binding-ab-php-5-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Weniger Code-Redundanz durch Design Patterns</title>
		<link>https://blog.ebene7.com/2010/08/27/weniger-code-redundanz-durch-design-patterns/</link>
		<comments>https://blog.ebene7.com/2010/08/27/weniger-code-redundanz-durch-design-patterns/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 05:00:27 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[CustomLibrary]]></category>
		<category><![CDATA[Custom_Model]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Factory]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[Strategy Pattern]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1287</guid>
		<description><![CDATA[Heute habe ich eine Artikel für euch, der mir besonders gefällt, weil er auf einfache Weise mehrere interessante Themen vereint. Und, wie sollte es auch anders sein, geht es wieder um unsere Models, um Entwurfsmuster und den Weltfrieden. *hust* Bevor &#8230; <a href="https://blog.ebene7.com/2010/08/27/weniger-code-redundanz-durch-design-patterns/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Heute habe ich eine Artikel für euch, der mir besonders gefällt, weil er auf einfache Weise mehrere interessante Themen vereint. Und, wie sollte es auch anders sein, geht es wieder um unsere Models, um Entwurfsmuster und den Weltfrieden. *hust*</p>
<p>Bevor ich aber nun der Miss World 2010 die Scherpe streitig mache, fange ich lieber mal an&#8230;</p>
<p><span id="more-1287"></span>Stellen wir uns mal vor, wir haben ein Meta-Model, welches verschiedene allgemeine Daten zu einem anderen Objekt speichern kann.</p>
<pre>&lt;?php
class MetaModel extends Custom_Model
{
  protected $_ownerId;
  protected $_creatorId;
  protected $_modifierId;
  protected $_createDate;
  protected $_modifyDate;

  // Weitere Felder und Getter/Setter
}</pre>
<p>Die ersten drei Felder sind jeweils UserIds und die anderen zwei Datumswerte, die wir über gewöhnliche Getter und Setter verändern können. Damit können wir schonmal mit den Daten arbeiten, jedoch leider nicht objektorientiert navigieren.</p>
<p>Mit Navigation meine ich einen einfachen und für Menschen leicht lesbaren Zugriff auf die Objekte. Im Prinzip nur eine einfache Methodenverkettung.</p>
<pre>&lt;?php
$ownerName = $object-&gt;getMeta()-&gt;getOwner()-&gt;getName();</pre>
<p>Anders herum will ich vielleicht auch die Möglichkeit haben ein Datum als String oder als Objekt zu setzen und will ganz sicher nicht in jedem einzelnen Setter die Unterscheidung implementieren.</p>
<p>Die Lösung ist denkbar einfach. Wir lagern den benötigten Code einfach aus! Wer sich etwas mit Design Patterns beschäftigt, der erkennt sicher das <a href="http://de.wikipedia.org/wiki/Strategy_Pattern" target="_blank">Strategy Pattern</a> wieder.</p>
<p>Als erstes definieren wir eine einfache Schnittstelle und bauen uns dannach einen &#8220;Accessor&#8221;.</p>
<pre>&lt;?php
interface Custom_Model_Access_Interface
{
  public function get($value);
  public function set($value);
}</pre>
<pre>&lt;?php
class Custom_Model_Access_User implements Custom_Model_Access_Interface
{
  /**
   * @param int $value
   * @return UserModel
  public function get($value)
  {
    // UserModel laden ($value==ID)
  }

  /**
   * @param mixed int|UserModel
   * @return int (UserId)
   */
  public function set($value)
  {
    // $value-&gt;getId() zurückgeben, wenn $value ein UserModel ist, sonst $value
  }
}</pre>
<p>Damit haben wir, wenn auch stark vereinfacht, die Logik ausgelagert und können sie nun in der Modelklasse nutzen. Für viele dieser Access-Objekte reicht eine Instanz aus, die wir am besten über eine einfache <a href="http://de.wikipedia.org/wiki/Factory_Pattern" target="_blank">Factory</a> erzeugen.</p>
<p>In unserem Model sieht das dann wie folgt aus.</p>
<pre>&lt;?php
class MetaModel extends Custom_Model
{
  // ...
  private $_accessUser;

  public function init()
  {
    $this-&gt;_accessUser = Custom_Model_Access_Factory::singleton('User');
  }

  public function getOwner()
  {
    return $this-&gt;_accessUser-&gt;get( $this-&gt;getOwnerId() );
  }

  public function setOwner($owner)
  {
    return $this-&gt;setOwnerId( $this-&gt;_accessUser-&gt;set($owner) );
  }
}</pre>
<p>Nach diesem Muster würden nun auch die Methoden für creator und modifier geschrieben werden. An dieser Stelle wäre auch ein einfacher Cache möglich, damit das Objekt nicht bei jedem Aufruf erneut instanziiert werden muss.</p>
<p>Das Access-Objekt für das Datum könnte unter Umständen etwas umfangreicher werden.</p>
<p>Der Getter sollte uns ein Datums-Objekt zurückgeben anhand des in der Datenbank (oder wo auch immer) gespeicherten Werten, egal in welchem Format dieser vorliegt.</p>
<p>Der Setter auf der andern Seite könnte z.B. sämtlichen gängigen Datums-Objekte und Stringformate kennen und diese in das übliche Y-m-d H:i:s-Format übersetzen.</p>
<p>Zusammenfassend lässt sich festhalten, dass sich diese Technik für alle möglichen Bereiche geeignet ist, wenn man Objekte zu den Ids haben möchte oder auch Formate umwandeln will oder muss (Datum, IP-Adressen etc.).</p>
<p>Wenn euch noch etwas sinnvolles zur Verwendung einfällt oder einfach noch Fragen oder Kritik offen sind, dann freue ich mich über Kommentare.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/08/27/weniger-code-redundanz-durch-design-patterns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Response-Objekt vs. echo, die() und exit</title>
		<link>https://blog.ebene7.com/2010/06/17/response-objekt-vs-echo-die-und-exit/</link>
		<comments>https://blog.ebene7.com/2010/06/17/response-objekt-vs-echo-die-und-exit/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 05:00:15 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Grundlagen]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Response]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=817</guid>
		<description><![CDATA[Eigentlich lohnt es sich ja fast nicht über etwas einfaches wie ein Response-Objekt einen Artikel zu schreiben. Fast, aber auch nur fast, denn die Praxis zeigt, dass es auch damit unerwartete Probleme geben kann. Alle, die bislang nur wenig oder &#8230; <a href="https://blog.ebene7.com/2010/06/17/response-objekt-vs-echo-die-und-exit/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Eigentlich lohnt es sich ja fast nicht über etwas einfaches wie ein Response-Objekt einen Artikel zu schreiben. Fast, aber auch nur fast, denn die Praxis zeigt, dass es auch damit unerwartete Probleme geben kann.</p>
<p><span id="more-817"></span>Alle, die bislang nur wenig oder keine Erfahrung mit MVC-Anwendungen gesammelt haben, werden sich vielleicht nun fragen, wofür dieses Objekt gut ist. Das Response-Objekt kontrolliert die komplette Ausgabe der Anwendung an den Client (z.B. einen Browser).</p>
<p>Während der kompletten Laufzeit können mit dem Objekt Ausgaben gesammelt und auch nachträglich verändert werden und auch die Reihenfolge spielt keine Rolle. So kann nun zuerst die Ausgabe gemacht werden und dann die Header gesetzt werden.</p>
<p>So müsste es klassisch mit PHP geschrieben werden:</p>
<pre><code>&lt;?php header('Content-type: text/xml'); echo $xml;</code></pre>
<p>Wenn wir nun die Reihenfolge vertauschen würden, hätte das eine Warning zur Folge.</p>
<pre><code>&lt;?php echo $xml; header('Content-type: text/xml');</code></pre>
<pre>Warning: Cannot modify header information - headers already sent by (output started at ####) in #### on line 3</pre>
<p>Wenn wir uns in einer MVC-Umgebung befinden, stellt diese Reihenfolge kein Problem dar, denn das Objekt verwaltet die Ausgabe und schickt alles zur rechten Zeit raus.</p>
<p>So könnte es dann z.B. in einer Action des Kontrollers aussehen:</p>
<pre><code>&lt;?php public function indexAction() { // ... $this-&gt;getResponse()-&gt;appendBody($xml); $this-&gt;getResponse()-&gt;setHeader('Content-type', 'text/xml'); } </code></pre>
<p>Neben den relativ harmlosen direkten Ausgaben mit echo oder print habe ich in den vergangenen Jahren auch Ausgaben mit die() gefunden. Die offensichtliche Arbeit verrichtet die Anwendung zwar in den Actions der Kontroller, aber es passiert unter Umständen auch vor- und nachher eine Menge. Letzteres würde dann unterbunden werden und evtl. wichtige Aufgaben nicht mehr abgearbeitet werden.</p>
<p>Ein Beispiel sah etwa so aus:</p>
<pre>&lt;?php
public function jsonAction()
{
  // ...
  header('Content-type: text/json');
  die($json);
  // ...
}</pre>
<p>Die Anwendung verliert so die Kontrolle über die Ausgabe und wird an der falschen Stelle beendet. Der richtige Weg führt auch hier zum Response-Objekt.</p>
<pre>&lt;?php
public function jsonAction()
{
  // ...
  $this-&gt;getResponse()-&gt;setHeader('COntent-type', 'text/json');
  $this-&gt;getResponse()-&gt;appendBody($json);
  return;  // &lt;== falls die Bearbeitung hier enden soll
  // ...
}</pre>
<p>So, nun gibt es in Zukunft keine Ausreden mehr, wenn irgendwo ein echo im Kontroller steht. Ich würde mich natürlich wie immer freuen eure Erfahrungen in den Kommentaren zu lesen.</p>
<p>Nebenbei bemerkt ist das mein 50. Artikel, also schon fast ein kleiner Grund zum Feiern. <img src='https://blog.ebene7.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/06/17/response-objekt-vs-echo-die-und-exit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementieren einer einfachen Plugin-Schnittstelle</title>
		<link>https://blog.ebene7.com/2010/05/12/implementieren-einer-einfachen-plugin-schnittstelle/</link>
		<comments>https://blog.ebene7.com/2010/05/12/implementieren-einer-einfachen-plugin-schnittstelle/#comments</comments>
		<pubDate>Wed, 12 May 2010 05:00:26 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Custom_Model]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[Magic Methods]]></category>
		<category><![CDATA[Model]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[SPL]]></category>
		<category><![CDATA[Strategy Pattern]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=766</guid>
		<description><![CDATA[Heute geht es darum, wie wir uns eine einfache Plugin-Schnittstelle für unsere Objekte bauen können. Als Beispiel, wie sollte es auch anders sein, eignet sich unsere Custom_Model-Klasse aus meinen vergangenen Artikeln. Und schon wieder die Frage, was kann unsere Klasse &#8230; <a href="https://blog.ebene7.com/2010/05/12/implementieren-einer-einfachen-plugin-schnittstelle/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Heute geht es darum, wie wir uns eine einfache Plugin-Schnittstelle für unsere Objekte bauen können. Als Beispiel, wie sollte es auch anders sein, eignet sich unsere Custom_Model-Klasse aus meinen <a href="http://blog.ebene7.com/2010/04/29/es-ist-ein-model-und-es-sieht-gut-aus/" target="_self">vergangenen Artikeln</a>.</p>
<p><span id="more-766"></span>Und schon wieder die Frage, was kann unsere Klasse dann mehr? Oder warum machen wir das?</p>
<p>Oftmals haben wir Objekte, die eine gewisse Menge identischer Methoden benötigen, jedoch nicht aus einer Vererbungslinie stammen.</p>
<p>Durch die Plugins können wir dann quasi Funktionen an unsere Objekte dran kleben und nutzen. Diesen Code müssen wir nur einmal schreiben, haben auch nur eine Stelle im Code zu pflegen und können dadurch sicherstellen, dass alles gleich funktioniert.</p>
<p>So erweitern wir nun also zuerst wie gewohnt unser <code>Custom_Model</code> um ein paar neue Methoden und Eigenschaften.</p>
<pre>&lt;?php
class Custom_Model implements Custom_Model_Interface
{
  // ...
  protected $_plugins;

  public function registerPlugin() {}
  public function unregisterPlugin() {}
  // ...
}</pre>
<p>Und das Interface für die Plugins.</p>
<pre>&lt;?php
interface Custom_Model_Plugin_Interface {}</pre>
<p>Beim Speichern der Plugins kommt wieder die Klasse <a href="http://de3.php.net/manual/de/class.splobjectstorage.php" target="_blank">SplObjectStorage</a> zum Einsatz, welche wir ja schon bei der <a href="http://blog.ebene7.com/2010/05/07/es-ist-ein-model-und-es-sieht-gut-aus-der-observer/" target="_self">Implementierung des Obeservers</a> verwendet haben. Demnach ist es auch nicht überraschend, dass die Registrierung an die Abmeldung der Plugins sehr einfach wird.</p>
<pre>public function registerPlugin(Custom_Model_Plugin_Interface $plugin)
{
  $this-&gt;_plugins-&gt;attach($plugin);
  return $this;
}

public function unregisterPlugin(Custom_Model_Plugin_Interface $plugin)
{
  $this-&gt;_plugins-&gt;detach($plugin);
  return $this;
}</pre>
<p>Die Models müssen das Interface <code>Custom_Model_Plugin_Interface</code> implementieren. Dieses Interface ist lediglich ein Flag- oder Marker-Interface, d.h. es schreibt keine Methoden vor.</p>
<p>Jetzt noch eine kleine Änderung an der Methode <code>__call()</code> und wir können schon mit dem Beispiel experimentieren.</p>
<pre>public function __call($method, $args)
{
  // Magie für die Getter &amp; Setter

  foreach($this-&gt;_plugins as $plugin) {
    if(method_exists($plugin, $method)) {
      array_unshift($args, $this);
      return call_user_func_array(array($plugin, $method), $args);
    }
  }

  // Fehlerbehandlung
}</pre>
<p>Durch <code>__call()</code> können wir unsere Plugin-Methoden so nutzen, als gehörten sie direkt zum Objekt. Die Art wie die Plugins verwendet werden  hat Vor-, aber auch Nachteile.</p>
<p>Die Liste der Plugins wird der Reihe nach durchlaufen und die erstbeste passende Methode wird aufgerufen. Auch die Getter oder Setter könnten wir nicht mehr überschreiben. Wenn das alles jedoch gewollt ist, dann lässt sich das aber auch mit wenigen Handgriffen erweitern.</p>
<p>Nun aber mal was praktisches zum Anschauen: Angenommen wir haben eine Model-Klasse mit Abhängigkeit zu anderen Objekten.</p>
<pre>&lt;?php
class Book extends Custom_Model
{
  protected $_id;
  protected $_title;
  protected $_ownerId;
}</pre>
<p>Nun wollen wir nicht nur die ID des Besitzers erfahren, sondern auch das Objekt das bekommen können. Dafür spendieren wir ein Plugin.</p>
<pre>&lt;?php
class GetOwnerPlugin implements Custom_Model_Plugin_Interface
{
  public function getOwner($sender)
  {
    $id = $sender-&gt;getOwnerId();

    // lade User-Objekt $owner anhand der $id

    return $owner;
  }
}</pre>
<p>Auf die Fehlerbehandlung habe ich an der Stelle mal verzichtet, sollte jedoch unbedingt stattfinden.</p>
<pre>&lt;?php
$book = new Book();
$book-&gt;registerPlugin(new GetOwnerPlugin());
$book-&gt;setOwnerId(42);
$owner = $book-&gt;getOwner();</pre>
<p>Spätestens hier fällt sicher nicht nur mir auf, dass das Konzept noch Lücken hat. Theoretisch kann es sein, dass zu verschiedenen IDs ein User-Objekt nachgeladen werden soll (<code>getAuthor()</code>, <code>getModifier()</code>, <code>getLastVisitor()</code>&#8230;) und dann bräuchten wir sämtliche Methoden in unserem Plugin oder verschiedene Plugins.</p>
<p>Dann hätten wir aber auch wieder mehrfachen Code und nichts gewonnen. Daher werde ich die Pluginschnittstelle noch etwas aufbohren und das Ergebnis dann in einem meiner nächsten Artikel vorstellen.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/05/12/implementieren-einer-einfachen-plugin-schnittstelle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
