程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> 實例講解PHP設計模式編程中的簡單工廠模式

實例講解PHP設計模式編程中的簡單工廠模式

編輯:PHP綜合

簡單工廠模式是類的創建模式,又叫做靜態工廠方法(Static Factory Method)模式。簡單工廠模式是由一個工廠對象決定創建出那一種產品類的實例。

1.工廠模式的幾種形態
工廠模式專門負責將大量有共同接口的類實例化。工廠模式可以動態決定將哪一個類實例化,不必事先知道每次要實例化哪一個類。工廠模式有以下幾種形態:
(1)簡單工廠(Simple Factory)模式,又稱靜態工廠方法模式(Static Factory Method Pattern)。
(2)工廠方法(Factory Method)模式,又稱多態性工廠(Polymorphic Factory)模式或虛擬構造子(Virtual Constructor)模式;
(3)抽象工廠(Abstract Factory)模式,又稱工具箱(Kit 或Toolkit)模式。下面就是簡單工廠模式的簡略類圖。

簡單工廠模式,或稱靜態工廠方法模式,是不同的工廠方法模式的一個特殊實現。在其他文獻中,簡單工廠往往作為普通工廠模式的一個特例討論。
學習簡單工廠模式是對學習工廠方法模式的一個很好的准備,也是對學習其他模式,特別是單例模式和多例模式的一個很好的准備。

2 .簡單工廠模式的引進

比如說有一個農場公司,專門向市場銷售各類水果。在這個系統裡需要描述下列的水果:
葡萄 Grape
草莓 Strawberry
蘋果 Apple
水果與其他的植物有很大的不同,就是水果最終是可以采摘食用的。那麼一個自然的作法就是建立一個各種水果都適用的接口,以便與農場裡的其他植物區分開。如下圖所示。

水果接口規定出所有的水果必須實現的接口,包括任何水果類必須具備的方法:種植plant(),生長grow()以及收獲harvest()。接口Fruit 的類圖如下所示。

這個水果接口的源代碼如下所示。
代碼清單1:接口Fruit 的源代碼

interface Fruit
{
public function grow();
public function harvest();
public function plant();
}

Apple 類是水果類的一種,因此它實現了水果接口所聲明的所有方法。另外,由於蘋果是多年生植物,因此多出一個treeAge 性質,描述蘋果樹的樹齡。下面是這個蘋果類的源代碼。
代碼清單2:類Apple 的源代碼

class Apple implements Fruit
{
private $_treeAge;
public function grow()
{
echo "Apple is growing.";
}
public function harvest()
{
echo "Apple has been harvested.";
}
public function plant()
{
echo "Apple has been planted.";
}
public function getTreeAge()
{
return $this->_treeAge;
}
public function setTreeAge($treeAge)
{
$this->_treeAge = (int) $treeAge;
}
}

同樣,Grape 類是水果類的一種,也實現了Fruit 接口所聲明的所有的方法。但由於葡萄分有籽和無籽兩種,因此,比通常的水果多出一個seedless 性質,如下圖所示。

葡萄類的源代碼如下所示。可以看出,Grape 類同樣實現了水果接口,從而是水果類型的一種子類型。
代碼清單3:類Grape 的源代碼

class Grape implements Fruit
{
private $seedless;
public function grow()
{
echo "Grape is growing.";
}
public function harvest()
{
echo "Grape has been harvested.";
}
public function plant()
{
echo "Grape has been planted.";
}
public function getSeedless()
{
return $this->seedless;
}
public function setSeedless($seedless)
{
$this->seedless = (boolean) $seedless;
}
}

Strawberry 類實現了Fruit 接口,因此,也是水果類型的子類型,其源代碼如下所示。
代碼清單4:類Strawberry 的源代碼

class Strawberry implements Fruit
{
public function grow()
{
echo "Strawberry is growing.";
}
public function harvest()
{
echo "Strawberry has been harvested.";
}
public function plant()
{
echo "Strawberry has been planted.";
}
}

農場的園丁也是系統的一部分,自然要由一個合適的類來代表。這個類就是FruitGardener 類,其結構由下面的類圖描述。

FruitGardener 類會根據客戶端的要求,創建出不同的水果對象,比如蘋果(Apple),葡萄(Grape)或草莓(Strawberry)的實例。而如果接到不合法的要求,FruitGardener 類會拋出BadFruitException 異常。
園丁類的源代碼如下所示。
代碼清單5:FruitGardener 類的源代碼

class FruitGardener
{
public static function factory($which)
{
$which = strtolower($which);
if ($which == 'apple') {
return new Apple();
} elseif ($which == 'strawberry') {
return new Strawberry();
} elseif ($which == 'grape') {
return new Grape();
} else {
throw new BadFruitException('Bad fruit request');
}
}
}

可以看出,園丁類提供了一個靜態工廠方法。在客戶端的調用下,這個方法創建客戶端所需要的水果對象。如果客戶端的請求是系統所不支持的,工廠方法就會拋出一個BadFruitException 異常。這個異常類的源代碼如下所示。
代碼清單6:BadFruitException 類的源代碼

class BadFruitException extends Exception
{
}

在使用時,客戶端只需調用FruitGardener 的靜態方法factory()即可。請見下面的示意
性客戶端源代碼。
代碼清單7:怎樣使用異常類BadFruitException

try {
FruitGardener::factory('apple');
FruitGardener::factory('grape');
FruitGardener::factory('strawberry');
//...
} catch (BadFruitException $e) {
//...
}

這樣,農場一定會百果豐收啦!

3.使用簡單工廠模式設計一個“面向對象的”計算器

/**
 * 面向對象計算器
 * 思路:
 * 1、面向對象的基本,封裝、繼承、多太
 * 2、父類公用類
 * 3、各種運算類
 */
 
/**
 * 基類,運算類
 * 只提供基本數據,不參與運算
 */
 
class Operation {
  
 // 第一個數
 public $first_num = 0;
  
 // 第二個數
 public $second_num = 0;
  
 /**
  * 獲取結果,其他類覆蓋此方法
  * @return double $result
  */
 public function getResult() {
  $result = 0.00;
   
  return $result;
 }
}
 
/**
 * 加法類
 */
class OperationAdd extends Operation {
 /**
  * 覆蓋父類,實現加法算法
  */
 public function getResult() {
  $result = 0;
  return $this->first_num + $this->second_num;
 }
}
 
/**
 * 減法類
 *
 */
class OperationSub extends Operation {
 /**
  * 覆蓋父類,實現加法算法
  */
 public function getResult() {
  $result = 0;
  return $this->first_num - $this->second_num;
 }
}
 
/**
 * 乘法類
 *
 */
class OperationMul extends Operation {
 /**
  * 覆蓋父類,實現加法算法
  */
 public function getResult() {
  $result = 0;
  return $this->first_num * $this->second_num;
 }
}
 
/**
 * 除類
 *
 */
class OperationDiv extends Operation {
 /**
  * 覆蓋父類,實現加法算法
  */
 public function getResult() {
  $result = 0;
   
  if ($this->second_num == 0) {
   throw new Exception('除法操作第二個參數不能為零!');
   return 0;
  }
   
  return $this->first_num / $this->second_num;
 }
}
 
/**
 * 工廠類
 */
class OperationFactory {
 /**
  * 工廠函數
  * @param string $operation
  * @return object
  */
 public function createOperation($operation) {
  $oper = null;
   
  switch($operation) {
   case '+':
    $oper = new OperationAdd();
    break;
   case '-':
    $oper = new OperationSub();
    break;
   case '*':
    $oper = new OperationMul();
    break;
   case '/':
    $oper = new OperationDiv();
    break;
   default:
    return 0;
  }
  return $oper;
 }
}
 
 
$operation = new OperationFactory();
$oper = $operation->createOperation('/');
 
$oper->first_num = 10;
$oper->second_num = 20;
var_dump($oper->getResult());

201622993823532.jpg (780×328)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved