2.3. Composite
2.3.1. Purpose
To treat a group of objects the same way as a single instance of theobject.
2.3.2. Examples
- a form class instance handles all its form elements like a singleinstance of the form, when
render()
is called, it subsequentlyruns through all its child elements and callsrender()
on them Zend_Config
: a tree of configuration options, each one is aZend_Config
object itself
2.3.3. UML Diagram
2.3.4. Code
You can also find this code on GitHub
RenderableInterface.php
- <?php
- namespace DesignPatterns\Structural\Composite;
- interface RenderableInterface
- {
- public function render(): string;
- }
Form.php
- <?php
- namespace DesignPatterns\Structural\Composite;
- /**
- * The composite node MUST extend the component contract. This is mandatory for building
- * a tree of components.
- */
- class Form implements RenderableInterface
- {
- /**
- * @var RenderableInterface[]
- */
- private $elements;
- /**
- * runs through all elements and calls render() on them, then returns the complete representation
- * of the form.
- *
- * from the outside, one will not see this and the form will act like a single object instance
- *
- * @return string
- */
- public function render(): string
- {
- $formCode = '<form>';
- foreach ($this->elements as $element) {
- $formCode .= $element->render();
- }
- $formCode .= '</form>';
- return $formCode;
- }
- /**
- * @param RenderableInterface $element
- */
- public function addElement(RenderableInterface $element)
- {
- $this->elements[] = $element;
- }
- }
InputElement.php
- <?php
- namespace DesignPatterns\Structural\Composite;
- class InputElement implements RenderableInterface
- {
- public function render(): string
- {
- return '<input type="text" />';
- }
- }
TextElement.php
- <?php
- namespace DesignPatterns\Structural\Composite;
- class TextElement implements RenderableInterface
- {
- /**
- * @var string
- */
- private $text;
- public function __construct(string $text)
- {
- $this->text = $text;
- }
- public function render(): string
- {
- return $this->text;
- }
- }
2.3.5. Test
Tests/CompositeTest.php
- <?php
- namespace DesignPatterns\Structural\Composite\Tests;
- use DesignPatterns\Structural\Composite;
- use PHPUnit\Framework\TestCase;
- class CompositeTest extends TestCase
- {
- public function testRender()
- {
- $form = new Composite\Form();
- $form->addElement(new Composite\TextElement('Email:'));
- $form->addElement(new Composite\InputElement());
- $embed = new Composite\Form();
- $embed->addElement(new Composite\TextElement('Password:'));
- $embed->addElement(new Composite\InputElement());
- $form->addElement($embed);
- // This is just an example, in a real world scenario it is important to remember that web browsers do not
- // currently support nested forms
- $this->assertEquals(
- '<form>Email:<input type="text" /><form>Password:<input type="text" /></form></form>',
- $form->render()
- );
- }
- }