php-doc-en/language/oop5/patterns.xml
2011-07-11 15:48:55 +00:00

171 lines
4.9 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<sect1 xml:id="language.oop5.patterns" xmlns="http://docbook.org/ns/docbook">
<title>Patterns</title>
<para>
Patterns are ways to describe best practices and good designs.
They show a flexible solution to common programming problems.
</para>
<sect2 xml:id="language.oop5.patterns.factory">
<title>Factory</title>
<para>
The Factory pattern allows for the instantiation of objects
at runtime. It is called a Factory Pattern since it is
responsible for "manufacturing" an object. A Parameterized Factory receives
the name of the class to instantiate as argument.
</para>
<example>
<title>Parameterized Factory Method</title>
<programlisting role="php">
<![CDATA[
<?php
class Example
{
// The parameterized factory method
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception('Driver not found');
}
}
}
?>
]]>
</programlisting>
<para>
Defining this method in a class allows drivers to be loaded on the
fly. If the <literal>Example</literal> class was a database
abstraction class, loading a <literal>MySQL</literal> and
<literal>SQLite</literal> driver could be done as follows:
</para>
<programlisting role="php">
<![CDATA[
<?php
// Load a MySQL Driver
$mysql = Example::factory('MySQL');
// Load an SQLite Driver
$sqlite = Example::factory('SQLite');
?>
]]>
</programlisting>
</example>
</sect2>
<sect2 xml:id="language.oop5.patterns.singleton">
<title>Singleton</title>
<para>
The Singleton ensures that there can be only one instance of a Class and provides a
global access point to that instance. Singleton is a "Gang of Four" Creational Pattern.
</para>
<para>The Singleton pattern is often implemented in Database Classes, Loggers, Front
Controllers or Request and Response objects.
</para>
<example>
<title xml:id="language.oop5.patterns.singleton.examples.basic">Singleton example</title>
<programlisting role="php"><![CDATA[
<?php
class Example
{
private static $instance;
private $count = 0;
private function __construct()
{
}
public static function singleton()
{
if (!isset(self::$instance)) {
echo 'Creating new instance.';
$className = __CLASS__;
self::$instance = new $className;
}
return self::$instance;
}
public function increment()
{
return $this->count++;
}
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup()
{
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
?>
]]>
</programlisting>
<para>Illustrated below is how the Singleton behaves</para>
<programlisting role="php"><![CDATA[
<?php
$singleton = Example::singleton(); // prints "Creating new instance."
echo $singleton->increment(); // 0
echo $singleton->increment(); // 1
$singleton = Example::singleton(); // reuses existing instance now
echo $singleton->increment(); // 2
echo $singleton->increment(); // 3
// all of these will raise a Fatal Error
$singleton2 = new Example;
$singleton3 = clone $singleton;
$singleton4 = unserialize(serialize($singleton));
?>
]]>
</programlisting>
</example>
<warning xml:id="warn.singleton.controversy">
<para>
The Singleton pattern is one of the more controversial patterns. Critics argue that
Singletons introduce Global State into an application and tightly couple the Singleton
and its consuming classes. This leads to hidden dependencies and unexpected side-effects,
which in turn leads to code that is harder to test and maintain.
</para>
<para>
Critics further argue that it is pointless to use a Singleton in a Shared Nothing Architecture
like PHP where objects are unique within the Request only anyways. It is easier and cleaner to
create collaborator object graphs by using Builders and Factory patterns once at the beginning
of the Request.
</para>
<para>
Singletons also violate several of the "SOLID" OOP design principles and the Law of Demeter.
Singletons cannot be serialized. They cannot be subtyped (before PHP 5.3) and won't be Garbage
Collected because of the instance being stored as a static attribute of the Singleton.
</para>
</warning>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->