php设计模式(二):简单工厂模式 (Simple Factory)
- 陈大剩
- 2022-11-17 23:47:13
- 862
简单工厂模式
简单工厂模式又称为静态工厂方法模型,它属于类创建型模式,简单工厂并不属于23种设计模式,刚开始学习设计模式的同学,对简单工厂模式、工厂方法、抽象工厂中的工厂一知半解,其实白话点来说:这些模式一定会有一个工厂类,子类并不需要知道工厂细节,只需新建工厂创建产品即好。
简单工厂模式的优点在于将对象的 创建 和 使用 分离,客户端只需要知道所需产品的名称或者类型,而不需要知道产品的具体实现细节。这样可以降低客户端的耦合度,同时也便于扩展和修改产品的实现。
问题
假设你正在开发一款组装DIY台式电脑
的应用,最初版本只需要拼装一台台式电脑并计算出每台总部件价格即可,因此大部分代码都在DIY台式电脑
的类中。
// DiyComputer.php
// 鼠标
$mouse = new Mouse();
$mousePrice = $mouse->getPrice();
// 键盘
$keyboard = new Keyboard();
$keyboardPrice = $keyboard->getPrice();
// 显示器
$display = new Display();
$displayPrice = $display->getPrice();
....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;
过了一段时间,使用DIY台式电脑
的用户都觉得普通有线键盘不好用,需要换成无线键盘,这时你可能需要对每个DIY台式电脑
的类修改键盘类代码。
// DiyComputer.php
// 鼠标
$mouse = new Mouse();
$mousePrice = $mouse->getPrice();
// 键盘
// $keyboard = new Keyboard();
$keyboard = new WirelessKeyboard();
$keyboardPrice = $keyboard->getPrice();
// 显示器
$display = new Display();
$displayPrice = $display->getPrice();
....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;
糟糕的是,如果以后这些DIY台式电脑
的用户需要换其它部件,很有可能需要再次对这些代码进行大幅度修改。
解决方案
简单工厂方法模式解决频繁更换各个部件,无法预知对象确切类别及其依赖关系时,可以用简单工厂方法。
白话文:需求频繁变动,没有切确的功能,避免代码多次重复改,可以采用此方法。
不需要客户端中去实例化某个类,客户端只需要穿一个产品名字给 简单工厂就行,简单工厂用 Switch
判断返回。
就如果老板让你做一件事,他不管你怎么做,只要结果,你负责过程,具体你去哪个部门借什么工具完成,老板不管你,那么这样老板是不是少了很多事呢?(减少了耦合),当然你的工作就变多了(谁叫你是打工人)。
STEP 1 建立产品类
建立一个产品基类。如 Product
产品基类。然后,确保所有部件实现产品基接口。例如,鼠标实现 产品 接口;所有部件都实现 键盘 接口,以此类推。
STEP 2 建立工厂
建立一个组装工厂,其中有 production
生产产品类方法,production
方法通过传入的值, Switch
选择创建对象。客户端知道工厂提供 所有的部件创建方法,但是并不关心其具体实现方式
结构
1个工厂
1个 interface 或者 abstract 产品基类
多个实现 interface 或者继承 abstract 的具体产品
代码示例
DIY台式电脑部件工厂类
//Factory.php
class Factory
{
/**
* 生产工厂
* @param string $product
* @return Product
*/
static public function production(string $product): Product
{
switch ($product) {
case 'mouse':
$result = new Mouse();
break;
case 'keyboard':
$result = new Keyboard();
break;
case 'display':
$result = new Display();
break;
default:
throw new \InvalidArgumentException('没有此部件');
}
return $result;
}
}
部件产品接口基类
// Product.php
interface Product
{
public function getPrice();
}
具体部件产品类
// Mouse.php
class Mouse implements Product
{
public function getPrice(): float
{
return 499.99;
}
}
// Keyboard.php
class Keyboard implements Product
{
public function getPrice(): float
{
return 149.99;
}
}
//Display.php
class Display implements Product
{
public function getPrice(): float
{
return 1499.99;
}
}
组装的DIY台式电脑类
DiyComputer.php
// 生成鼠标
$mouse = Factory::production('mouse');
$mousePrice = $mouse->getPrice();
// 生成键盘
$keyboard = Factory::production('keyboard');
$keyboardPrice = $keyboard->getPrice();
// 生成显示器
$display = Factory::production('display');
$displayPrice = $display->getPrice();
....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;
uml
优缺点
优点
- 可以避免具体产品和创建者之间紧密耦合。
缺点
- 工厂需要引入很多新的子类,代码可能会因此变得更复杂。
- 违背了开闭原则,添加新的部件必须去工厂类中修改循环语句