本文同步更新於blog
情境:運輸系統,用來取得當前機型名稱等資訊
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern;
class Program
{
/**
* @param string $model
* @return string
*/
public function getModel($model)
{
switch ($model) {
case 'LocalTrain':
return '區間車';
break;
case 'LimitedExpress':
return '自強號';
break;
}
}
}
需求一:新增復興號 (SemiExpress)
正當我們想直接在switch中新增一個case時,
發現這種做法違反了開放封閉原則。
明明是新增機型,卻修改到了既有的程式碼(取得機型名稱)。
此外在修改機型名稱時,也會修改到既有程式碼。
讓我們用簡單工廠模式,將創建物件與物件本身的職責分離。
(註:客戶端的程式碼、創建機型、機型本身,共三種職責)
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts;
interface Model
{
public function getName();
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern\Model;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts\Model;
class LocalTrain implements Model
{
public function getName()
{
return '區間車';
}
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern\Model;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts\Model;
class LimitedExpress implements Model
{
public function getName()
{
return '自強號';
}
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Model\LocalTrain;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Model\LimitedExpress;
class RailWayModelFactory
{
/**
* @param string $model
* @return Model
*/
public function createModel($model): Model
{
switch ($model) {
case 'LocalTrain':
return new LocalTrain();
break;
case 'LimitedExpress':
return new LimitedExpress();
break;
}
}
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern;
use App\FactoryPattern\Transport\SimpleFactoryPattern\RailwayModelFactory;
class Program
{
/**
* @param string $model
* @return string
*/
public function getModel($model)
{
$railwayModelFactory = new RailwayModelFactory();
$model = $railwayModelFactory->createModel($model);
return $model->getName();
}
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern\Model;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts\Model;
class SemiExpress implements Model
{
public function getName()
{
return '復興號';
}
}
<?php
namespace App\FactoryPattern\Transport\SimpleFactoryPattern;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Model\LocalTrain;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Model\LimitedExpress;
use App\FactoryPattern\Transport\SimpleFactoryPattern\Model\SemiExpress;
class RailWayModelFactory
{
/**
* @param string $model
* @return Model
*/
public function createModel($model): Model
{
switch ($model) {
case 'LocalTrain':
return new LocalTrain();
break;
case 'LimitedExpress':
return new LimitedExpress();
break;
case 'SemiExpress':
return new SemiExpress();
break;
}
}
}
[單一職責原則]
[開放封閉原則]
[依賴反轉原則]
透過簡單工廠模式,運輸系統類別減少了改變的機會,
但創建類別依然常常需要變更。
最後附上類別圖:
(註:若不熟悉 UML 類別圖,可參考UML類別圖說明。)
ʕ •ᴥ•ʔ:不久之後,我們還會見到這個範例,敬請期待。