Pattern: 蠅量模式
Class Diagram: 文字積木
情境:這是公司生產的文字積木
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <?php
namespace App\Flyweight\Blocks;
class ConcreteBlock {
protected $shape;
public $word;
public function __construct(string $shape, string $word) { $this->shape = $shape; $this->word = $word; }
public function getShape(): string { return $this->shape; }
public function getWord(): string { return $this->word; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| namespace App\Flyweight\Blocks; <?php
namespace App\Flyweight\Blocks;
use App\Flyweight\Blocks\ConcreteBlock;
class Program {
public function getBlocks(): array { $firstBlock = new ConcreteBlock('star', 'B'); $secondBlock = new ConcreteBlock('square', 'E'); $thirdBlock = new ConcreteBlock('square', 'A'); $fourthBlock = new ConcreteBlock('square', 'R');
return [$firstBlock, $secondBlock, $thirdBlock, $fourthBlock]; } }
|
隨著積木越賣越好,我們會創建出許多Block,
它們要顯示的文字各不相同,但形狀大概就那幾種。
我們決定改變積木的實作,不紀錄顯示文字於積木的狀態中。
抽離出共用的形狀部分,來節省記憶體的消耗。
1 2 3 4 5 6 7 8 9
| <?php
namespace App\Flyweight\Blocks\Contracts;
interface Block { public function getShape(); public function display(string $word): string; }
|
之後我們要顯示文字時,會使用display()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?php
namespace App\Flyweight\Blocks;
use App\Flyweight\Blocks\Contracts\Block;
class ConcreteBlock implements Block {
protected $shape;
public function __construct(string $shape) { $this->shape = $shape; }
public function getShape(): string { return $this->shape; }
public function display(string $word): string { return $word; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php
namespace App\Flyweight\Blocks;
use App\Flyweight\Blocks\ConcreteBlock; use App\Flyweight\Blocks\Contracts\Block;
class BlockFactory {
protected $blocks;
public function getBlock(string $shape): Block { if (!isset($this->blocks[$shape])) { $this->blocks[$shape] = new ConcreteBlock($shape); }
return $this->blocks[$shape]; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php
namespace App\Flyweight\Blocks;
use App\Flyweight\Blocks\Block;
class Program {
public function getBlocks(): array { $blockFactory = new BlockFactory();
$firstBlock = $blockFactory->getBlock('star');
$secondBlock = $blockFactory->getBlock('square');
$thirdBlock = $blockFactory->getBlock('square');
$fourthBlock = $blockFactory->getBlock('square');
return [$firstBlock, $secondBlock, $thirdBlock, $fourthBlock]; } }
|
當客戶端要顯示文字時,再呼叫display()方法。
[單一職責原則]
我們將管理內部狀態與管理外部狀態,視為兩種不同的職責。
透過區分兩者,我們便可以用簡單工廠模式搭配單例模式,
切出細粒度的物件,來共用相同的程式碼。
其蠅量類別只紀錄內部狀態且創建後便不會改變。
[開放封閉原則]
透過工廠,我們可以修改積木本身的實作(例如換廠牌),而不影響客戶端。
當客戶端修改外部狀態時,也不影響原本純內部狀態的積木。
[依賴反轉原則]
工廠依賴於抽象的積木介面。
實體積木實作了抽象的積木介面。
ʕ •ᴥ•ʔ:原來共享經濟是用了蠅量模式的概念啊。