本文同步更新於blog
前情提要:铁路运输系统,参考范例:运输系统(工厂方法模式)
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use ReflectionClass;
class Program
{
/**
* @param string $model
* @return string
*/
public function getModel($model)
{
$modelFactory = $this->createModelFactory($model);
$model = $modelFactory->createModel();
return $model->getName();
}
/**
* @param string $model
* @return ModelFactory
*/
private function createModelFactory($model)
{
$namespace = 'App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories';
$className = $model . 'Factory';
$reflector = new ReflectionClass($namespace . '\\' . $className);
return $reflector->newInstance();
}
}
需求一:各交通工具准备就绪,要开始处理内装问题。
由於不同的机型会有不同的内装,让我们从定义椅子介面开始。
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts;
interface Chair
{
public function getName();
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
interface ModelFactory
{
public function createModel(): Model;
public function createChair(): Chair;
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
class LongChair implements Chair
{
public function getName()
{
return '长型座椅';
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
class ReservedSeatChair implements Chair
{
public function getName()
{
return '对号座椅';
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
class PlaneChair implements Chair
{
public function getName()
{
return '飞机座椅';
}
}
接着改写各个机型工厂,选择适合的座椅。
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Model\LocalTrain;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Chair\LongChair;
class LocalTrainFactory implements ModelFactory
{
public function createModel(): Model
{
//取得生产材料...
//招募技术团队...
return new LocalTrain();
}
public function createChair(): Chair
{
return new LongChair();
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Model\SemiExpress;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Chair\ReservedSeatChair;
class SemiExpressFactory implements ModelFactory
{
public function createModel(): Model
{
//取得生产材料...
//招募技术团队...
return new SemiExpress();
}
public function createChair(): Chair
{
return new ReservedSeatChair();
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Model\LimitedExpress;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Chair\ReservedSeatChair;
class LimitedExpressFactory implements ModelFactory
{
public function createModel(): Model
{
//取得生产材料...
//招募技术团队...
return new LimitedExpress();
}
public function createChair(): Chair
{
return new ReservedSeatChair();
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Model;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Model\Boeing747;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\Chair;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Chair\PlaneChair;
class Boeing747Factory implements ModelFactory
{
public function createModel(): Model
{
//取得生产材料...
//招募技术团队..
return new Boeing747();
}
public function createChair(): Chair
{
return new PlaneChair();
}
}
<?php
namespace App\FactoryPattern\Transport\AbstractFactoryPattern;
use App\FactoryPattern\Transport\AbstractFactoryPattern\Contracts\ModelFactory;
use ReflectionClass;
class Program
{
/**
* @param string $model
* @return string
*/
public function getModel($model)
{
$modelFactory = $this->createModelFactory($model);
$model = $modelFactory->createModel();
return $model->getName();
}
/**
* @param string $model
* @return string
*/
public function getChair($model)
{
$modelFactory = $this->createModelFactory($model);
$chair = $modelFactory->createChair();
return $chair->getName();
}
/**
* @param string $model
* @return ModelFactory
*/
private function createModelFactory($model)
{
$namespace = 'App\FactoryPattern\Transport\AbstractFactoryPattern\ModelFactories';
$className = $model . 'Factory';
$reflector = new ReflectionClass($namespace . '\\' . $className);
return $reflector->newInstance();
}
}
透过工厂介面,我们组合了各种类型产品。
使得不同类型的产品之间,有了产品族的联系关系。
[单一职责原则]
我们将工厂类别 (Creator) 与产品类别 (Product) 视作两种不同的职责。
[开放封闭原则]
当新增新的产品族时,我们仅需新增工厂类别。
当修改既有产品时,我们仅需修改其产品类别,不会影响到其他的产品类别。
[介面隔离原则]
工厂介面:用来创建机型及座椅。
产品介面:用来创建对应的产品。
[依赖反转原则]
工厂介面依赖於抽象的机型介面与座椅介面。
工厂实作抽象的工厂介面。
机型实作抽象的机型介面。
座椅实作抽象的座椅介面。
最後附上类别图:
(注:若不熟悉 UML 类别图,可参考UML类别图说明。)
ʕ •ᴥ•ʔ:虽然有点复杂,但这个模式好美。
>>: HERE API Example - 使用 Platform Data Extension REST API 显示邮递区号图层
Warning与error直扑而来XDD 蛮头痛的,我目前遇到的有两个问题被回报为Bug。 简单来说...
前言 今日的程序码 => GITHUB 讲解官方范例的权限、扫描、广播的部分。官方范例是使用 ...
0x1 前言 目前还没有画面可以看或操作,所以单就资料流的部分先写进资料库, 而建立订单目前也是先塞...
这篇开始基本上是进入持续分析有哪些未完善的部份需要进行补足。 依照这几次的bootlog的部份分析,...
Final Calculator Design <!DOCTYPE html> <...