diff --git a/Structural/Flyweight/CharacterFlyweight.php b/Structural/Flyweight/CharacterFlyweight.php index 02657c1..d1e7954 100644 --- a/Structural/Flyweight/CharacterFlyweight.php +++ b/Structural/Flyweight/CharacterFlyweight.php @@ -16,22 +16,16 @@ class CharacterFlyweight implements FlyweightInterface */ private $name; - /** - * @param string $name - */ - public function __construct($name) + public function __construct(string $name) { $this->name = $name; } - /** - * Clients supply the context-dependent information that the flyweight needs to draw itself - * For flyweights representing characters, extrinsic state usually contains e.g. the font. - * - * @param string $font - */ - public function draw($font) + public function render(string $font): string { - print_r("Character {$this->name} printed $font \n"); + // Clients supply the context-dependent information that the flyweight needs to draw itself + // For flyweights representing characters, extrinsic state usually contains e.g. the font. + + return sprintf('Character %s with font %s', $this->name, $font); } } diff --git a/Structural/Flyweight/FlyweightFactory.php b/Structural/Flyweight/FlyweightFactory.php index 10a0d4d..a295a22 100644 --- a/Structural/Flyweight/FlyweightFactory.php +++ b/Structural/Flyweight/FlyweightFactory.php @@ -3,38 +3,26 @@ namespace DesignPatterns\Structural\Flyweight; /** - * A factory manages shared flyweights. Clients shouldn't instaniate them directly, + * A factory manages shared flyweights. Clients should not instantiate them directly, * but let the factory take care of returning existing objects or creating new ones. */ -class FlyweightFactory +class FlyweightFactory implements \Countable { /** - * Associative store for flyweight objects. - * - * @var array + * @var CharacterFlyweight[] */ - private $pool = array(); + private $pool = []; - /** - * Magic getter. - * - * @param string $name - * - * @return Flyweight - */ - public function __get($name) + public function get(string $name): CharacterFlyweight { - if (!array_key_exists($name, $this->pool)) { + if (!isset($this->pool[$name])) { $this->pool[$name] = new CharacterFlyweight($name); } return $this->pool[$name]; } - /** - * @return int - */ - public function totalNumber() + public function count(): int { return count($this->pool); } diff --git a/Structural/Flyweight/FlyweightInterface.php b/Structural/Flyweight/FlyweightInterface.php index b12290d..032a1be 100644 --- a/Structural/Flyweight/FlyweightInterface.php +++ b/Structural/Flyweight/FlyweightInterface.php @@ -2,13 +2,7 @@ namespace DesignPatterns\Structural\Flyweight; -/** - * An interface through which flyweights can receive and act on extrinsic state. - */ interface FlyweightInterface { - /** - * @param string $extrinsicState - */ - public function draw($extrinsicState); + public function render(string $extrinsicState): string; } diff --git a/Structural/Flyweight/Tests/FlyweightTest.php b/Structural/Flyweight/Tests/FlyweightTest.php index 997c3df..5f63456 100644 --- a/Structural/Flyweight/Tests/FlyweightTest.php +++ b/Structural/Flyweight/Tests/FlyweightTest.php @@ -4,33 +4,28 @@ namespace DesignPatterns\Structural\Flyweight\Tests; use DesignPatterns\Structural\Flyweight\FlyweightFactory; -/** - * FlyweightTest demonstrates how a client would use the flyweight structure - * You don't have to change the code of your client. - */ class FlyweightTest extends \PHPUnit_Framework_TestCase { - private $characters = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ); - private $fonts = array('Arial', 'Times New Roman', 'Verdana', 'Helvetica'); - - // This is about the number of characters in a book of average length - private $numberOfCharacters = 300000; + private $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; + private $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica']; public function testFlyweight() { $factory = new FlyweightFactory(); - for ($i = 0; $i < $this->numberOfCharacters; $i++) { - $char = $this->characters[array_rand($this->characters)]; - $font = $this->fonts[array_rand($this->fonts)]; - $flyweight = $factory->$char; - // External state can be passed in like this: - // $flyweight->draw($font); + foreach ($this->characters as $char) { + foreach ($this->fonts as $font) { + $flyweight = $factory->get($char); + $rendered = $flyweight->render($font); + + $this->assertEquals(sprintf('Character %s with font %s', $char, $font), $rendered); + } } // Flyweight pattern ensures that instances are shared // instead of having hundreds of thousands of individual objects - $this->assertLessThanOrEqual($factory->totalNumber(), count($this->characters)); + // there must be one instance for every char that has been reused for displaying in different fonts + $this->assertCount(count($this->characters), $factory); } } diff --git a/Structural/Flyweight/uml/Flyweight.uml b/Structural/Flyweight/uml/Flyweight.uml index 5d53b0f..61c78dd 100644 --- a/Structural/Flyweight/uml/Flyweight.uml +++ b/Structural/Flyweight/uml/Flyweight.uml @@ -1,25 +1,24 @@ PHP - \DesignPatterns\Structural\Flyweight\FlyweightFactory + \DesignPatterns\Structural\Flyweight\CharacterFlyweight - \DesignPatterns\Structural\Flyweight\CharacterFlyweight - \DesignPatterns\Structural\Flyweight\FlyweightFactory - \DesignPatterns\Structural\Flyweight\FlyweightInterface + \DesignPatterns\Structural\Flyweight\CharacterFlyweight + \DesignPatterns\Structural\Flyweight\FlyweightFactory + \DesignPatterns\Structural\Flyweight\FlyweightInterface - - + + - + Fields Constants - Constructors Methods private diff --git a/Structural/Flyweight/uml/uml.png b/Structural/Flyweight/uml/uml.png index 1209ab4..26af3e3 100644 Binary files a/Structural/Flyweight/uml/uml.png and b/Structural/Flyweight/uml/uml.png differ diff --git a/Structural/Flyweight/uml/uml.svg b/Structural/Flyweight/uml/uml.svg index b46aa2f..fc0d70b 100644 --- a/Structural/Flyweight/uml/uml.svg +++ b/Structural/Flyweight/uml/uml.svg @@ -1,466 +1,503 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - - + + - + - - + + - - + + - - + + - - + + - - - - - - name + + - - + + - - + + - - - - - - __construct(name) + + + name - - + + - - + + - - - - - - draw(font) + + - - + + - - - + + + render(font) - - + + - - CharacterFlyweight + + + - - CharacterFlyweight + + - - + + CharacterFlyweight - - + + CharacterFlyweight - - + + - - - - - - name + + - - + + - - + + - - - - - - __construct(name) + + - - + + - - + + + name - - - - - - draw(font) + + - - + + - - - + + - - + + - - CharacterFlyweight + + - - CharacterFlyweight + + + render(font) - - + + - - + + + - - + + - - + + CharacterFlyweight - - - - - - pool + + CharacterFlyweight - - + + - - + + - - - - - - __get(name) + + - - + + - - - - - - totalNumber() + + - - + + - - - + + - - + + + pool - - FlyweightFactory + + - - FlyweightFactory + + - - + + - - + + - - + + + get(name) - - - - - - pool + + - - + + - - + + - - - - - - __get(name) + + + count() - - + + - - - - - - totalNumber() + + + - - + + - - - + + FlyweightFactory - - + + FlyweightFactory - - FlyweightFactory + + - - FlyweightFactory + + - - + + - - + + - - + + - - + + - - - - - - draw(extrinsicState) + + + pool - - + + - - - + + - - + + - - FlyweightInterface + + - - FlyweightInterface + + - - + + + get(name) - - + + - - + + - - - - - - draw(extrinsicState) + + - - + + - - - + + + count() - - + + - - FlyweightInterface + + + - - FlyweightInterface + + + + + FlyweightFactory + + + FlyweightFactory + + + + + + + + + + + + + + + + + + + + + + render(extrinsicState) + + + + + + + + + + + + + FlyweightInterface + + + FlyweightInterface + + + + + + + + + + + + + + + + + + + + + + render(extrinsicState) + + + + + + + + + + + + + FlyweightInterface + + + FlyweightInterface - + - +