工廠方法 Factory Method

工廠方法,跟抽象工廠有點像,可是又沒那麼像,抽象工廠的工廠會有個抽象類別,並且把工廠要做且會重工的事情寫在抽象類別當中,而工廠方法則是需要定義一個工廠介面,並且讓工廠去實作,如果看到工廠介面不小心定義成抽象工廠,就拿網子打他,有點像是曹賣的奶奶會賣大頭菜,曹賣也會賣大頭菜,所以他們都有一個介面定義他們會賣大頭菜。

UML

實作

首先我們一樣要先建立大頭菜介面,並且定義大頭菜需要有哪些功能,再來建立健康的大頭菜、壞掉的大頭菜,先有大頭菜才有大頭菜工廠。

TurnipsContract.php

/**

* Interface TurnipsContract.

*/

interface TurnipsContract

{

public function calculatePrice(): int;

}

然後我們要新增新鮮的大頭菜、壞掉的大頭菜,並且去實作大頭菜介面所定義的條件。

Turnips.php

/**

* Class Turnips.

*/

class Turnips implements TurnipsContract

{

/**

* @var int

*/

protected $price;

/**

* @var int

*/

protected $count;

/**

* Turnips constructor.

*

* @param int $price

* @param int $count

*/

public function __construct(int $price, int $count)

{

$this->price = $price;

$this->count = $count;

}

/**

* @return int

*/

public function calculatePrice(): int

{

if (isset($this->price) && isset($this->count)) {

return $this->price * $this->count;

} else {

return 0;

}

}

}

SpoiledTurnips.php

/**

* Class SpoiledTurnips.

*/

class SpoiledTurnips implements TurnipsContract

{

/**

* @var int

*/

protected $price;

/**

* @var int

*/

protected $count;

/**

* SpoiledTurnips constructor.

*

* @param int $price

* @param int $count

*/

public function __construct(int $price, int $count)

{

$this->price = $price;

$this->count = $count;

}

/**

* @return int

*/

public function calculatePrice(): int

{

if (isset($this->count)) {

return 0 * $this->count;

} else {

return 0;

}

}

}

接下來我們要建立個別的大頭菜工廠,分別是健康的大頭菜工廠、壞掉的大頭菜工廠,但在此之前,我們要先定義什麼是工廠。

FactoryContract.php

/**

* Interface TurnipsFactoryContract.

*/

interface TurnipsFactoryContract

{

public function createTurnips(int $price, int $count): TurnipsContract;

}

定義完工廠以後,我們最後要來建立健康的大頭菜工廠、壞掉的大頭菜工廠。

TurnipsFactory.php

/**

* Class TurnipsFactory.

*/

class TurnipsFactory implements FactoryContract

{

/**

* @param int $price

* @param int $count

*

* @return TurnipsContract

*/

public function createTurnips(int $price, int $count): TurnipsContract

{

return new Turnips($price, $count);

}

}

SpoiledTurnipsFactory.php

/**

* Class SpoiledTurnipsFactory.

*/

class SpoiledTurnipsFactory implements FactoryContract

{

/**

* @var int

*/

const SPOILED_PRICE = 0;

/**

* @param int $price

* @param int $count

*

* @return TurnipsContract

*/

public function createTurnips(int $price, int $count): TurnipsContract

{

return new SpoiledTurnips(self::SPOILED_PRICE, $count);

}

}

測試

最後我們要來測試我們寫的大頭菜工廠方法是否可以正常運作,因此會有幾個需要測試的重點項目:

測試是否能夠建立健康的大頭菜。

測試是否能夠建立壞掉的大頭菜。

測試健康的大頭菜是否能夠正常計算價格。

測試壞掉的大頭菜是否能夠正常計算價格。

/**

* Class FactoryMethodTest.

*/

class FactoryMethodTest extends TestCase

{

/**

* 測試是否能夠正常建立大頭菜。

*

* @test

*/

public function test_can_create_turnips()

{

$factory = new TurnipsFactory(100, 40);

$turnips = $factory->createTurnips();

$this->assertInstanceOf(Turnips::class, $turnips);

}

/**

* 測試是否能夠正常建立壞掉的大頭菜。

*

* @test

*/

public function test_can_create_spoiled_turnips()

{

$factory = new SpoiledTurnipsFactory(40);

$turnips = $factory->createTurnips();

$this->assertInstanceOf(SpoiledTurnips::class, $turnips);

}

/**

* 測試是否能夠正常計算大頭菜的價格。

*

* @test

*/

public function test_can_calculate_price_for_turnips()

{

$factory = new TurnipsFactory(100, 40);

$turnips = $factory->createTurnips();

$this->assertEquals(4000, $turnips->calculatePrice());

}

/**

* 測試是否能夠正常計算壞掉的大頭菜的價格。

*

* @test

*/

public function test_can_calculate_price_for_spoiled_turnips()

{

$factory = new SpoiledTurnipsFactory(40);

$turnips = $factory->createTurnips();

$this->assertEquals(0, $turnips->calculatePrice());

}

}

最後測試的執行結果會獲得如下:

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)

完整程式碼

參考文獻

php factory interface,【PHP 設計模式大頭菜】工廠方法 Factory Method相关推荐

  1. php interface的设计,【PHP、設計模式、大頭菜】流暢介面 Fluent Interface

    September 29, 2020 2 min to read [PHP.設計模式.大頭菜]流暢介面 Fluent Interface 流暢介面 Fluent Interface 流暢介面,常用於撰 ...

  2. C#適應練習:幾種常見設計模式的實現

    一.單例及原型模式 單例:即使用一個固定對象的對象進行操作,實現起來很簡單 using System; using System.Collections.Generic; using System.L ...

  3. 設計模式之王 - MVC

    Model-View-Controller (縮寫 MVC ) 是 Cocoa 框架的一部分,並且毋庸置疑是最常用的設計模式之一.它可以幫你把物件根據職責進行劃分和歸類. 作為劃分依據的三個基本職責是 ...

  4. Java 設計模式 - 適配器模式

    Java 設計模式 - 適配器模式 適配器模式前言 模式概述 模式結構 模式具體應用 類適配器模式 對象適配器模式 優缺點 適配器模式前言 在現實生活中,經常出現兩個對象因接口不兼容而不能在一起工作的 ...

  5. C++設計模式——策略模式

    模式定義:策略模式定義了算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶. 舉個例子來説,不同鴨子的行爲是不同的,我們可以把變化的行爲提取出來進行封裝.我將鴨子的飛 ...

  6. Java 設計模式 - 觀察者模式

    Java設計模式-觀察者模式 什麼是觀察者模式? 觀察者模式的結構 代碼實現 實際案例 什麼是觀察者模式? 首先先來看看一個對於觀察者模式一個經典的描述,出自於阎宏博士的 <JAVA與模式> ...

  7. C++設計模式——觀察者模式

    觀察者模式:定義了對象之閒的一對多依賴,這樣一來,儅一個對象改變狀態時,它的所有依賴者都會收到通知並自動更新. 觀察者模式的類圖: 代碼示例 :利用WeatherData對象取得數據,更新concre ...

  8. 設計模式之Visitor

    Visitor定義 作用於某個物件群中各個物件的操作. 它可以使你在不改變這些物件本身的情況下,定義作用於這些物件的新操作. 在Java中,Visitor模式實際上是分離了collection結構中的 ...

  9. ‎平面設計師需要瞭解的8個印刷知識‎

    作為一個平面設計師,有必要保留同學習印刷知識. 有啲設計好似好靚,但印刷品與效果圖相去甚遠: 相反,有啲設計草稿睇落微不足道,但系佢哋可以通過設計師要求嘅印刷工藝同印刷資料去到好好印刷效果. 有咩唔同 ...

最新文章

  1. 《R in Action》读书笔记(1)
  2. P3121 [USACO15FEB]审查(黄金)Censoring (Gold)
  3. 【公告】【公告】【公告】【公告】
  4. python contextlib closing
  5. 加菲猫的人生歪理~ 看完果然开心,哈哈~
  6. css3的高级而有用且很少人知道的属性和样式
  7. Raspberry install wine
  8. eatwhatApp开发实战(二)
  9. 全网首发:C++中通过POST向服务器发送JSON的代码
  10. 微信或者QQ如何制作请用右上角打开浏览器
  11. 软件测试 atp,ATP使用方法详细-内部资料-软件测试文档类资源
  12. APP、软件版本号的命名规范与原则
  13. Postgresql中xlog生成和清理逻辑
  14. 12款免费图标生成器
  15. SQL必知必会【笔记】
  16. python获取时间戳字符串
  17. CIO免费IT预算计划模板
  18. 批处理批量替换word内容的思路
  19. Gnuradio+uhd驱动软件安装流程
  20. 计算机网络专业规划建设,计算机网络工程专业建设

热门文章

  1. 浅谈全局视角下的设计模式
  2. python自动演奏Freepiano【双手合奏】
  3. 成都跨境电商浅析印度跨境出口电商的机会和风险!
  4. 在 Cinema 4D 中使用 Octane 渲染的物质工作流程
  5. 进口奥迪S6让人无法忽视的低调
  6. Linux中用户和权限管理
  7. 阿里云域名解析网络和服务架构设计(二) 之云解析DNS-全局流量管理
  8. 地下蚁国EotU for Mac/win(模拟建设类游戏)
  9. 火蚁机器人_科学网—红火蚁的“生命之舟” - 赵序茅的博文
  10. 银河麒麟V10安装教程