一文读懂简单工厂、工厂方法、抽象工厂
发布:smiling 来源: PHP粉丝网 添加日期:2022-07-19 11:45:22 浏览: 评论:0
基本上每个人手机里都有一款音乐播放器,目前流行的播放器有:QQ音乐、酷狗音乐、搜狗音乐、网易云音乐、天天动听等。下面是一段关于播放音乐的代码:
- if ($type == 'QQ') {
- $player = new QQPlayer();
- } else if ($type == 'Wy') {
- $player = new WyPlayer();
- } else if ($type == 'KG') {
- $player = new KGPlayer();
- } else {
- $palyer = null;
- }
- $player->on(); // 打开播放器
- $player->choiceMusic('我不配'); // 选择歌曲
- $player->play(); // 开始播放
为了时代码的逻辑更加清晰、可读性更好,我们要善于把功能独立的代码块封装成函数。按照这个设计思路,我们可以将其中的条件分支抽离出来,单独放在一个类中的方法中。这个类,我们就可以叫做简单工厂模式。
简单工厂模式的定义:一个类可以根据不同的参数来获取不同的实例,一般这些被创建的实例都具有相同的父类。
静态工厂模式:一般的,我们将简单工厂模式中的用于创建不同实例的方法设置为静态方法,避免创建多个相同实例。
下面我们用简单工厂模式改写上面的代码
- class MusicPlayerFactory
- {
- public static function create ($type)
- {
- if ($type == 'QQ') {
- $player = new QQPlayer();
- } else if ($type == 'Wy') {
- $player = new WyPlayer();
- } else if ($type == 'KG') {
- $player = new KGPlayer();
- } else {
- $player = null;
- }
- return $player;
- }
- }
- // 业务代码修改如下
- $player = MusicPlayerFactory:create('QQ');
- $player->on(); // 打开播放器
- $player->choiceMusic('我不配'); // 选择歌曲
- $player->play(); // 开始播放
对于上面的简单工厂模式,如果我们需要添加新的音乐播放器,就一定会修改MusicPlayerFactory的create方法,这有点不符合“开闭原则”。对于这种条件分支不是很多,另外类的创建也非常的简单,使用简单工厂模式是完全可以的。如果非要将if分支逻辑去掉,使他符合“开闭原则”,那么就可以使用工厂方法来实现。对于工厂方法,也不是一定比简单工厂模式要好,虽然它的扩展性比较好,但是牺牲了可读性。
工厂方法模式
定义:在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
现在我们用“多态”来消除掉上面简单工厂模式的if分支结构。实现的代码如下所示:
- interface IMusicPlayerFactory
- {
- static function create ();
- }
- class QQPlayerFactory implements IMusicPlayerFactory
- {
- public static function create ()
- {
- return new QQPlayer();
- }
- }
- class WyPlayerFactory implements IMusicPlayerFactory
- {
- public static function create ()
- {
- return new WyPlayer();
- }
- }
- class KGPlayerFactory implements IMusicPlayerFactory
- {
- public static function create ()
- {
- return new KGPlayer();
- }
- }
- // 业务代码修改如下
- if ($type == 'QQ') {
- $player = QQPlayerFactory::create();
- } else if ($type == 'Wy') {
- $player = WyPlayerFactory::create();
- } else if ($type == 'KG') {
- $player = KGPlayerFactory::create();
- } else {
- throw new \Exception('...');
- }
- $player->on(); // 打开播放器
- $player->choiceMusic('我不配'); // 选择歌曲
- $player->play(); // 开始播放
可以看到,问题又回到了原点,业务代码里又出现了if条件分支结构。那么怎么去解决该问题呢?
我们可以为工厂类再创建一个简单工厂,用来创建工厂类对象。新的简单工厂代码如下:
- class MusicPlayerFactoryMap
- {
- const Players = [
- 'QQ' => 'QQPlayerFactory',
- 'Wy' => 'WyPlayerFactory',
- 'KG' => 'KGPlayerFactory'
- ];
- public static function getPlayerFactory (string $type)
- {
- if (emptyempty($type)) {
- return null;
- }
- return (self::Players[$type])::create();
- }
- }
- // 业务代码修改如下
- $palyer = MusicPlayerFactoryMap::getPlayerFactory('QQ')
- $player->on(); // 打开播放器
- $player->choiceMusic('我不配'); // 选择歌曲
- $player->play(); // 开始播放
可以看到,使用了工厂模式,结构变的比之前复杂的多。如果来的创建实例过程复制,我们才会推荐使用工厂方法模式。
抽象工厂模式
抽象工厂模式使用场景比较特殊,用的比较少。在工厂方法模式中,具体工厂负责生产具体的产品,每一个工厂对应一个具体产品。但有时候,我们需要一个工厂可以创建多个产品对象,而不是一个单一的产品。
我们用一个例子来看看:对象电脑厂是负责生产电脑来出售的。我们知道,电脑是由主机、键盘、显示器以及鼠标组成的,目前对象电脑城只生产3种电脑,低配、中配和高配的,不同配置的电脑使用的主机品牌、显示器品牌等都是不同的。
主机目前有:麒麟主机、雷霆主机、冬日主机
键盘目前有:雷柏、罗技、雷蛇
显示器目前有:aoc、hkc、BenQ
鼠标目前有:罗技、灵蛇、方正
顶配版电脑由麒麟主机、雷柏键盘、aoc显示器、罗技鼠标组成,中配由……。
关于主机的代码如下:
- interface Host
- {
- static function createHost ();
- }
- class DrHost implements Host
- {
- public static function createHost()
- {
- echo '创建冬日主机' . PHP_EOL;
- }
- }
- class QlHost implements Host
- {
- public static function createHost()
- {
- echo '创建麒麟主机' . PHP_EOL;
- }
- }
- class LtHost implements Host
- {
- public static function createHost()
- {
- echo '创建雷霆主机' . PHP_EOL;
- }
- }
类似的,去创建键盘、显示器、鼠标,代码这里就不贴了。
现在,我们定义一个创建电脑的接口。
- interface ComputerFactory
- {
- static function createHost ();
- static function createKeyboard ();
- static function createMonitor ();
- static function createMouse ();
- }
然后完成三个具体工厂用于创建低配、中配以及高配版电脑。
- class GreatComputerFactory implements ComputerFactory
- {
- public static function createHost()
- {
- QlHost::createHost();
- }
- public static function createKeyboard()
- {
- LbKeyboard::createKeyboard();
- }
- public static function createMonitor()
- {
- AocMonitor::createMonitor();
- }
- public static function createMouse()
- {
- LjMouse::createMouse();
- }
- }
- class GoodComputerFactory implements ComputerFactory
- {
- public static function createHost()
- {
- LtHost::createHost();
- }
- public static function createKeyboard()
- {
- LjKeyboard::createKeyboard();
- }
- public static function createMonitor()
- {
- HkcMonitor::createMonitor();
- }
- public static function createMouse()
- {
- LsMouse::createMouse();
- }
- }
- class NormalComputerFactory implements ComputerFactory
- {
- public static function createHost()
- {
- DrHost::createHost();
- }
- public static function createKeyboard()
- {
- LsKeyboard::createKeyboard();
- }
- public static function createMonitor()
- {
- BenqMonitor::createMonitor();
- }
- public static function createMouse()
- {
- FzMouse::createMouse();
- }
- }
现在可以来创建具体的电脑了
- class GreatComputer
- {
- public function __construct()
- {
- echo '高配电脑' . PHP_EOL;
- GreatComputerFactory::createHost();
- GreatComputerFactory::createKeyboard();
- GreatComputerFactory::createMonitor();
- GreatComputerFactory::createMouse();
- }
- }
- class GoodComputer
- {
- public function __construct()
- {
- echo '中配电脑' . PHP_EOL;
- GoodComputerFactory::createHost();
- GoodComputerFactory::createKeyboard();
- GoodComputerFactory::createMonitor();
- GoodComputerFactory::createMouse();
- }
- }
- class NormalComputer
- {
- public function __construct()
- {
- echo '低配电脑' . PHP_EOL;
- NormalComputerFactory::createHost();
- NormalComputerFactory::createKeyboard();
- NormalComputerFactory::createMonitor();
- NormalComputerFactory::createMouse();
- }
- }
Tags: 简单工厂 工厂方法 抽象工厂
- 上一篇:学习php-fpm服务启动脚本的方法
- 下一篇:最后一页
相关文章
- ·php工厂方法模式是什么(2022-07-18)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)