單例模式 Singleton Pattern 單例模式,整個應用程式只會有一個實體,這個實體不會重複建立,就有點像是整座島上只有一個曹賣,這個曹賣在你這座島的時間,你可以盡量找他買大頭菜,無論你做什麼事情,大頭菜在這段時間內都不會任意更動,你的曹賣是你的曹賣,不會因為你進去博物館逛一圈再出來而改變。
UML
實作 我們需要建立一個大頭菜類別,裡面放著一顆大頭菜。
Turnips.php
1 2 3 4 5 6 7 8 9 10 final class Turnips { protected static $turnips ; }
再來我們需要有個方法來獲得這顆大頭菜,並且這顆大頭菜只要被建立過,無論怎麼建立大頭菜,所獲得的物件永遠會是第一顆大頭菜。
Turnips.php
1 2 3 4 5 6 7 8 9 10 11 12 13 public static function getTurnips ( ): Turnips { if (static ::$turnips === null ) { static ::$turnips = new static (); } return static ::$turnips ; }
最後為了防止大頭菜被用各種意想不到的 BUG 來建立,所以要設下種種防線。
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 private function __construct ( ) { } private function __clone ( ) { } private function __wakeup ( ) { }
測試 最後為了驗證我們前面所撰寫的大頭菜是否正確,我們需要寫個測試,測試建立兩個大頭菜,並且獲取大頭菜物件,比對一下兩個是不是都是大頭菜,以及兩個是不是一樣的大頭菜。
SingletonPatternTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 use PHPUnit \Framework \TestCase ;class SingletonPatternTest extends TestCase { public function test_uniqueness ( ) { $turnipsA = Turnips ::getTurnips (); $turnipsB = Turnips ::getTurnips (); $this ->assertInstanceOf (Turnips ::class , $turnipsA ); $this ->assertInstanceOf (Turnips ::class , $turnipsB ); $this ->assertSame ($turnipsA , $turnipsB ); } }
最後測試的執行結果會獲得如下:
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)
完整程式碼 設計模式不難,找回快樂而已,以大頭菜為例。
參考文獻