PHP7 AbstractFactory

This commit is contained in:
Dominik Liebler
2016-09-22 15:19:18 +02:00
parent 370ce4dd93
commit f03c173eb9
17 changed files with 650 additions and 671 deletions

View File

@@ -3,38 +3,10 @@
namespace DesignPatterns\Creational\AbstractFactory; namespace DesignPatterns\Creational\AbstractFactory;
/** /**
* class AbstractFactory.
*
* Sometimes also known as "Kit" in a GUI libraries.
*
* 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 * In this case, the abstract factory is a contract for creating some components
* for the web. There are two components : Text and Picture. There are two ways * for the web. There are two ways of rendering text: HTML and JSON
* of rendering : HTML or JSON.
*
* Therefore 4 concrete classes, but the client just needs 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
{ {
/** abstract public function createText(string $content): Text;
* Creates a text component.
*
* @param string $content
*
* @return Text
*/
abstract public function createText($content);
/**
* Creates a picture component.
*
* @param string $path
* @param string $name
*
* @return Picture
*/
abstract public function createPicture($path, $name = '');
} }

View File

@@ -1,18 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory\Html;
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
class Picture extends BasePicture
{
/**
* some crude rendering from HTML output.
*
* @return string
*/
public function render()
{
return sprintf('<img src="%s" title="%s"/>', $this->path, $this->name);
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory\Html;
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
class Text extends BaseText
{
/**
* some crude rendering from HTML output.
*
* @return string
*/
public function render()
{
return '<div>'.htmlspecialchars($this->text).'</div>';
}
}

View File

@@ -4,28 +4,8 @@ namespace DesignPatterns\Creational\AbstractFactory;
class HtmlFactory extends AbstractFactory class HtmlFactory extends AbstractFactory
{ {
/** public function createText(string $content): Text
* Creates a picture component.
*
* @param string $path
* @param string $name
*
* @return Html\Picture|Picture
*/
public function createPicture($path, $name = '')
{ {
return new Html\Picture($path, $name); return new HtmlText($content);
}
/**
* Creates a text component.
*
* @param string $content
*
* @return Html\Text|Text
*/
public function createText($content)
{
return new Html\Text($content);
} }
} }

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
class HtmlText extends Text
{
// do something here
}

View File

@@ -1,18 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory\Json;
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
class Picture extends BasePicture
{
/**
* some crude rendering from JSON output.
*
* @return string
*/
public function render()
{
return json_encode(array('title' => $this->name, 'path' => $this->path));
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory\Json;
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
class Text extends BaseText
{
/**
* some crude rendering from JSON output.
*
* @return string
*/
public function render()
{
return json_encode(array('content' => $this->text));
}
}

View File

@@ -4,28 +4,8 @@ namespace DesignPatterns\Creational\AbstractFactory;
class JsonFactory extends AbstractFactory class JsonFactory extends AbstractFactory
{ {
/** public function createText(string $content): Text
* Creates a picture component.
*
* @param string $path
* @param string $name
*
* @return Json\Picture|Picture
*/
public function createPicture($path, $name = '')
{ {
return new Json\Picture($path, $name); return new JsonText($content);
}
/**
* Creates a text component.
*
* @param string $content
*
* @return Json\Text|Text
*/
public function createText($content)
{
return new Json\Text($content);
} }
} }

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
class JsonText extends Text
{
// do something here
}

View File

@@ -1,19 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
/**
* Interface MediaInterface.
*
* This contract is not part of the pattern, in general case, each component
* are not related
*/
interface MediaInterface
{
/**
* some crude rendering from JSON or html output (depended on concrete class).
*
* @return string
*/
public function render();
}

View File

@@ -1,26 +0,0 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
abstract class Picture implements MediaInterface
{
/**
* @var string
*/
protected $path;
/**
* @var string
*/
protected $name;
/**
* @param string $path
* @param string $name
*/
public function __construct($path, $name = '')
{
$this->name = (string) $name;
$this->path = (string) $path;
}
}

View File

@@ -39,45 +39,21 @@ HtmlFactory.php
:language: php :language: php
:linenos: :linenos:
MediaInterface.php
.. literalinclude:: MediaInterface.php
:language: php
:linenos:
Picture.php
.. literalinclude:: Picture.php
:language: php
:linenos:
Text.php Text.php
.. literalinclude:: Text.php .. literalinclude:: Text.php
:language: php :language: php
:linenos: :linenos:
Json/Picture.php JsonText.php
.. literalinclude:: Json/Picture.php .. literalinclude:: JsonText.php
:language: php :language: php
:linenos: :linenos:
Json/Text.php HtmlText.php
.. literalinclude:: Json/Text.php .. literalinclude:: HtmlText.php
:language: php
:linenos:
Html/Picture.php
.. literalinclude:: Html/Picture.php
:language: php
:linenos:
Html/Text.php
.. literalinclude:: Html/Text.php
:language: php :language: php
:linenos: :linenos:

View File

@@ -2,43 +2,24 @@
namespace DesignPatterns\Creational\AbstractFactory\Tests; namespace DesignPatterns\Creational\AbstractFactory\Tests;
use DesignPatterns\Creational\AbstractFactory\AbstractFactory;
use DesignPatterns\Creational\AbstractFactory\HtmlFactory; use DesignPatterns\Creational\AbstractFactory\HtmlFactory;
use DesignPatterns\Creational\AbstractFactory\JsonFactory; use DesignPatterns\Creational\AbstractFactory\JsonFactory;
/**
* AbstractFactoryTest tests concrete factories.
*/
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
{ {
public function getFactories() public function testCanCreateHtmlText()
{ {
return array( $factory = new HtmlFactory();
array(new JsonFactory()), $text = $factory->createText('foobar');
array(new HtmlFactory()),
); $this->assertInstanceOf('DesignPatterns\Creational\AbstractFactory\HtmlText', $text);
} }
/** public function testCanCreateJsonText()
* This is the client of factories. Note that the client does not
* care which factory is given to him, he can create any component he
* wants and render how he wants.
*
* @dataProvider getFactories
*/
public function testComponentCreation(AbstractFactory $factory)
{ {
$article = array( $factory = new JsonFactory();
$factory->createText('Lorem Ipsum'), $text = $factory->createText('foobar');
$factory->createPicture('/image.jpg', 'caption'),
$factory->createText('footnotes'),
);
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article); $this->assertInstanceOf('DesignPatterns\Creational\AbstractFactory\JsonText', $text);
/* this is the time to look at the Builder pattern. This pattern
* helps you to create complex object like that article above with
* a given Abstract Factory
*/
} }
} }

View File

@@ -2,18 +2,15 @@
namespace DesignPatterns\Creational\AbstractFactory; namespace DesignPatterns\Creational\AbstractFactory;
abstract class Text implements MediaInterface abstract class Text
{ {
/** /**
* @var string * @var string
*/ */
protected $text; private $text;
/** public function __construct(string $text)
* @param string $text
*/
public function __construct($text)
{ {
$this->text = (string) $text; $this->text = $text;
} }
} }

View File

@@ -1,38 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Diagram> <Diagram>
<ID>PHP</ID> <ID>PHP</ID>
<OriginalElement>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</OriginalElement> <OriginalElement>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</OriginalElement>
<nodes> <nodes>
<node x="281.0" y="228.0">\DesignPatterns\Creational\AbstractFactory\Html\Text</node> <node x="214.0" y="101.0">\DesignPatterns\Creational\AbstractFactory\JsonFactory</node>
<node x="150.0" y="229.0">\DesignPatterns\Creational\AbstractFactory\Html\Picture</node> <node x="107.0" y="0.0">\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node>
<node x="223.0" y="117.0">\DesignPatterns\Creational\AbstractFactory\HtmlFactory</node> <node x="0.0" y="101.0">\DesignPatterns\Creational\AbstractFactory\HtmlFactory</node>
<node x="0.0" y="117.0">\DesignPatterns\Creational\AbstractFactory\JsonFactory</node> <node x="111.0" y="298.0">\DesignPatterns\Creational\AbstractFactory\JsonText</node>
<node x="126.0" y="0.0">\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node> <node x="0.0" y="298.0">\DesignPatterns\Creational\AbstractFactory\HtmlText</node>
<node x="0.0" y="229.0">\DesignPatterns\Creational\AbstractFactory\MediaInterface</node> <node x="51.5" y="197.0">\DesignPatterns\Creational\AbstractFactory\Text</node>
</nodes> </nodes>
<notes /> <notes />
<edges> <edges>
<edge source="\DesignPatterns\Creational\AbstractFactory\HtmlFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory"> <edge source="\DesignPatterns\Creational\AbstractFactory\HtmlText" target="\DesignPatterns\Creational\AbstractFactory\Text">
<point x="0.0" y="-33.5" /> <point x="0.0" y="-14.5" />
<point x="324.5" y="92.0" /> <point x="45.5" y="273.0" />
<point x="256.5" y="92.0" /> <point x="75.75" y="273.0" />
<point x="43.5" y="33.5" /> <point x="-24.25" y="25.5" />
</edge> </edge>
<edge source="\DesignPatterns\Creational\AbstractFactory\JsonFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory"> <edge source="\DesignPatterns\Creational\AbstractFactory\JsonText" target="\DesignPatterns\Creational\AbstractFactory\Text">
<point x="0.0" y="-33.5" /> <point x="0.0" y="-14.5" />
<point x="101.5" y="92.0" /> <point x="154.5" y="273.0" />
<point x="169.5" y="92.0" /> <point x="124.25" y="273.0" />
<point x="-43.5" y="33.5" /> <point x="24.25" y="25.5" />
</edge> </edge>
</edges> <edge source="\DesignPatterns\Creational\AbstractFactory\JsonFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
<settings layout="Hierarchic Group" zoom="1.0" x="213.0" y="138.0" /> <point x="0.0" y="-25.5" />
<SelectedNodes /> <point x="311.0" y="76.0" />
<Categories> <point x="252.5" y="76.0" />
<Category>Fields</Category> <point x="48.5" y="25.5" />
<Category>Constants</Category> </edge>
<Category>Constructors</Category> <edge source="\DesignPatterns\Creational\AbstractFactory\HtmlFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
<Category>Methods</Category> <point x="0.0" y="-25.5" />
</Categories> <point x="97.0" y="76.0" />
<VISIBILITY>private</VISIBILITY> <point x="155.5" y="76.0" />
</Diagram> <point x="-48.5" y="25.5" />
</edge>
</edges>
<settings layout="Hierarchic Group" zoom="1.0" x="117.0" y="130.5" />
<SelectedNodes>
<node>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node>
</SelectedNodes>
<Categories>
<Category>Methods</Category>
<Category>Constants</Category>
<Category>Fields</Category>
</Categories>
<VISIBILITY>private</VISIBILITY>
</Diagram>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 90 KiB