物件池模式 Pool Pattern 物件池模式,每次的買賣都是致富的關鍵,致富不能只靠 40 顆大頭菜,靠的是放滿整座島的大頭菜,因此你需要有個島專門放大頭菜,放得滿滿的,到了關鍵時刻再把大頭菜拿出來賣。
UML
實作 首先我們會需要把大頭菜定義出來,並且賦予幾些簡單的功能。
Turnips.php
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 class Turnips { protected $price ; protected $count ; public function __construct (int $price , int $count ) { $this ->price = $price ; $this ->count = $count ; } public function calculatePrice ( ): int { if (isset ($this ->price) && isset ($this ->count)) { return $this ->price * $this ->count; } else { return 0 ; } } }
再來我們要做一個大頭菜池,而且要挖深,挖深呢,好處是有利於儲大頭菜,未來還可以養大頭菜,然後就可以把大頭菜通通丟進去。
TurnipsPool.php
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 use Countable ;class TurnipsPool implements Countable { protected $pool = []; protected $total = 0 ; public function get (string $key = null ): Turnips { if (isset ($key )) { $turnips = $this ->pool[$key ]; unset ($this ->pool[$key ]); } else { $turnips = array_pop ($this ->pool); } $this ->total -= $turnips ->calculatePrice (); return $turnips ; } public function set (Turnips $turnips ): string { $key = spl_object_hash ($turnips ); $this ->total += $turnips ->calculatePrice (); $this ->pool[$key ] = $turnips ; return $key ; } public function total ( ): int { return $this ->total; } public function count ( ): int { return count ($this ->pool); } }
額外補充 Countable 繼承 Countable
這個類別可以使用 count()
這個方法,因此需要實作它。
1 2 3 4 class Countable { abstract public count ( void ) : int }
測試 最後為了測試我們挖很深的大頭菜池是否能夠養大頭菜,所以我們有兩組測試要做:
測試是否能夠正常的新增 10 組大頭菜,並且把大頭菜拿出 2 組後,檢查池子裡面是否剩下 8 組大頭菜,然後比較一下拿出來的這 2 組是不是兩個不同的大頭菜,最後比較一下大頭菜池子裡的大頭菜價格是不是正確的。
測試是否能夠正常的新增 10 組大頭菜,並且把大頭菜拿出 1 組後,馬上把大頭菜丟回去池子裡,再從池子裡拿出 1 組大頭菜,檢查池子裡面是否剩下 9 組大頭菜,然後比較一下最後拿出來的這組,是不是就是一開始拿出來的那組大頭菜,最後比較一下大頭菜池子裡的大頭菜價格是不是正確的。
PoolPatternTest.php
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class PoolPatternTest extends TestCase { public function test_can_set_new_turnips_and_get ( ) { $pool = new TurnipsPool (); for ($i = 0 ; $i < 10 ; $i ++) { $turnips = new Turnips (100 , 40 ); $pool ->set ($turnips ); } $turnips1 = $pool ->get (); $turnips2 = $pool ->get (); $this ->assertCount (8 , $pool ); $this ->assertNotSame ($turnips1 , $turnips2 ); $this ->assertEquals (32000 , $pool ->total ()); } public function test_can_get_turnips_twice_when_set_it_first ( ) { $pool = new TurnipsPool (); for ($i = 0 ; $i < 10 ; $i ++) { $turnips = new Turnips (100 , 40 ); $pool ->set ($turnips ); } $turnips1 = $pool ->get (); $pool ->set ($turnips1 ); $turnips2 = $pool ->get (); $this ->assertCount (9 , $pool ); $this ->assertSame ($turnips1 , $turnips2 ); $this ->assertEquals (36000 , $pool ->total ()); } }
最後測試的執行結果會獲得如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PHPUnit Pretty Result Printer 0.28.0 by Codedungeon and contributors. ==> Configuration: ~/php-design-pattern/vendor/codedungeon/phpunit-result-printer/src/phpunit-printer.yml PHPUnit 9.2.6 by Sebastian Bergmann and contributors. ==> AbstractFactoryTest ✔ ✔ ✔ ✔ ==> BuilderPatternTest ✔ ✔ ==> FactoryMethodTest ✔ ✔ ✔ ✔ ==> PoolPatternTest ✔ ✔ ==> PrototypePatternTest ✔ ✔ ==> SimpleFactoryTest ✔ ✔ ✔ ✔ ==> SingletonPatternTest ✔ ==> StaticFactoryTest ✔ ✔ ✔ ✔ ✔ Time: 00:00.050, Memory: 6.00 MB OK (24 tests, 68 assertions)
完整程式碼 設計模式不難,找回快樂而已,以大頭菜為例。
參考文獻