简单工厂模式
简单工厂模式又称为静态工厂方法模型,它属于类创建型模式,简单工厂并不属于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台式电脑
的用户需要换其它部件,很有可能需要再次对这些代码进行大幅度修改。
解决方案
简单工厂方法模式解决频繁更换各个部件,无法预知对象确切类别及其依赖关系时,可以用简单工厂方法。
白话文:需求频繁变动,没有切确的功能,避免代码多次重复改,可以采用此方法。
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 + ...;
优缺点
优点
- 可以避免具体产品和创建者之间紧密耦合。
缺点
- 工厂需要引入很多新的子类,代码可能会因此变得更复杂。
- 违背了开闭原则,添加新的部件必须去工厂类中修改循环语句