mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-08-04 14:07:25 +02:00
a REAL abstract factory not a helper-like full of static
This commit is contained in:
@@ -1,42 +1,43 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns;
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract Factory pattern
|
* Abstract Factory pattern
|
||||||
*
|
*
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* to create series of related or dependant objects without specifying their concrete classes,
|
* to create series of related or dependant objects without specifying their concrete classes,
|
||||||
* usually the created classes all implement the same interface
|
* usually the created classes all implement the same interface. The client of the abstract
|
||||||
|
* factory does not care about how these objects are created, he just knows they goes together.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Sometimes also known as "Kit" in a GUI libraries.
|
||||||
* - A Factory to create media in a CMS: classes would be text, audio, video, picture
|
|
||||||
* - SQL Factory (types are all strings with SQL, but they vary in detail (tables, fields, etc.))
|
|
||||||
* - Zend Framework: Zend_Form::createElement() creates form elements, but you could also call new T
|
|
||||||
* TextElement() instead
|
|
||||||
* - an abstract factory to create various exceptions (e.g. Doctrine2 uses this method)
|
|
||||||
*
|
*
|
||||||
|
* This design pattern implements the Dependency Inversion Principle since
|
||||||
|
* it is the concrete subclass which creates concrete components.
|
||||||
|
*
|
||||||
|
* In this case, the abstract factory is a contract for creating some components
|
||||||
|
* for the web. There are two components : Text and Picture. There is two ways
|
||||||
|
* of rendering : HTML or JSON.
|
||||||
|
*
|
||||||
|
* Therefore 4 concretes classes, but the client just need to know this contract
|
||||||
|
* to build a correct http response (for a html page or for an ajax request)
|
||||||
*/
|
*/
|
||||||
abstract class AbstractFactory
|
abstract class AbstractFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @static
|
* Creates a text component
|
||||||
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
* @return AbstractFactory\Text
|
* @return Text
|
||||||
*/
|
*/
|
||||||
public static function createText($content)
|
abstract public function createText($content);
|
||||||
{
|
|
||||||
return new AbstractFactory\Text($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @static
|
* Createss a picture component
|
||||||
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return AbstractFactory\Picture
|
* @return Picture
|
||||||
*/
|
*/
|
||||||
public static function createPicture($path, $name = '')
|
abstract public function createPicture($path, $name = '');
|
||||||
{
|
|
||||||
return new AbstractFactory\Picture($path, $name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
23
AbstractFactory/Html/Picture.php
Normal file
23
AbstractFactory/Html/Picture.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory\Html;
|
||||||
|
|
||||||
|
use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picture is a concrete image for HTML rendering
|
||||||
|
*/
|
||||||
|
class Picture extends BasePicture
|
||||||
|
{
|
||||||
|
|
||||||
|
// some crude rendering from HTML output
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return sprintf('<img src="%s" title="$s"/>', $this->_path, $this->_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
AbstractFactory/Html/Text.php
Normal file
22
AbstractFactory/Html/Text.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory\Html;
|
||||||
|
|
||||||
|
use DesignPatterns\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text is a concrete text for HTML rendering
|
||||||
|
*/
|
||||||
|
class Text extends BaseText
|
||||||
|
{
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return "<div>" . htmlspecialchars($this->_text) . '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
AbstractFactory/HtmlFactory.php
Normal file
25
AbstractFactory/HtmlFactory.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HtmlFactory is a concrete factory for HTML component
|
||||||
|
*/
|
||||||
|
class HtmlFactory extends AbstractFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public function createPicture($path, $name = '')
|
||||||
|
{
|
||||||
|
return new Html\Picture($path, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createText($content)
|
||||||
|
{
|
||||||
|
return new Html\Text($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
AbstractFactory/Json/Picture.php
Normal file
23
AbstractFactory/Json/Picture.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory\Json;
|
||||||
|
|
||||||
|
use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picture is a concrete image for JSON rendering
|
||||||
|
*/
|
||||||
|
class Picture extends BasePicture
|
||||||
|
{
|
||||||
|
|
||||||
|
// some crude rendering from JSON output
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return json_encode(array('title' => $this->_name, 'path' => $this->_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
AbstractFactory/Json/Text.php
Normal file
22
AbstractFactory/Json/Text.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory\Json;
|
||||||
|
|
||||||
|
use DesignPatterns\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text is a text component with a JSON rendering
|
||||||
|
*/
|
||||||
|
class Text extends BaseText
|
||||||
|
{
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return json_encode(array('content' => $this->_text));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
AbstractFactory/JsonFactory.php
Normal file
26
AbstractFactory/JsonFactory.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsonFactory is a factory for creating a family of JSON component
|
||||||
|
* (example for ajax)
|
||||||
|
*/
|
||||||
|
class JsonFactory extends AbstractFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public function createPicture($path, $name = '')
|
||||||
|
{
|
||||||
|
return new Json\Picture($path, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createText($content)
|
||||||
|
{
|
||||||
|
return new Json\Text($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This contract is not part of the pattern, in general case, each component
|
||||||
|
* are not related
|
||||||
|
*/
|
||||||
interface Media
|
interface Media
|
||||||
{
|
{
|
||||||
|
|
||||||
|
function render();
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
class Picture implements Media
|
abstract class Picture implements Media
|
||||||
{
|
{
|
||||||
protected $_path;
|
protected $_path;
|
||||||
protected $_name;
|
protected $_name;
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
class Text implements Media
|
abstract class Text implements Media
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
45
Tests/AbstractFactory/AbstractFactoryTest.php
Normal file
45
Tests/AbstractFactory/AbstractFactoryTest.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DesignPatternPHP
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DesignPatterns\Tests\AbstractFactory;
|
||||||
|
|
||||||
|
use DesignPatterns\AbstractFactory\AbstractFactory;
|
||||||
|
use DesignPatterns\AbstractFactory\HtmlFactory;
|
||||||
|
use DesignPatterns\AbstractFactory\JsonFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractFactoryTest tests concrete factories
|
||||||
|
*/
|
||||||
|
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function getFactories()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(new JsonFactory()),
|
||||||
|
array(new HtmlFactory())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the client of factories. Note that the client does not
|
||||||
|
* care which fatory is given to him, it can create any component he
|
||||||
|
* want and render how he wants.
|
||||||
|
*
|
||||||
|
* @dataProvider getFactories
|
||||||
|
*/
|
||||||
|
public function testComponentCreation(AbstractFactory $factory)
|
||||||
|
{
|
||||||
|
$article = array(
|
||||||
|
$factory->createText('Lorem Ipsum'),
|
||||||
|
$factory->createPicture('/image.jpg', 'caption'),
|
||||||
|
$factory->createText('footnotes')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertContainsOnly('DesignPatterns\AbstractFactory\Media', $article);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user