一文读懂简单工厂、工厂方法、抽象工厂

2025-04-28 10:15:03 5
  • 收藏
  • 管理
    简单工厂模式 基本上每个人手机里都有一款音乐播放器,目前流行的播放器有:QQ音乐、酷狗音乐、酷狗音乐、网易云音乐、天天动听等。下面是一段关于播放音乐的代码: 复制if($type ==QQ){ $player =newQQPlayer();}elseif($type ==Wy){ $player =newWyPlayer();}elseif($type ==KG){ $player =newKGPlayer();}else{ $palyer =null;} $player->on();// 打开播放器 $player->choiceMusic(我不配);// 选择歌曲 $player->play();// 开始播放 为了时代码的逻辑更加清晰、可读性更好,我们要善于把功能独立的代码块封装成函数。按照这个设计思路,我们可以将其中的条件分支抽离出来,单独放在一个类中的方法中。这个类,我们就可以叫做简单工厂模式。 简单工厂模式的定义:一个类可以根据不同的参数来获取不同的实例,一般这些被创建的实例都具有相同的父类。 静态工厂模式:一般的,我们将简单工厂模式中的用于创建不同实例的方法设置为静态方法,避免创建多个相同实例。 下面我们用简单工厂模式改写上面的代码 复制classMusicPlayerFactory{publicstaticfunction create ($type){if($type ==QQ){ $player =newQQPlayer();}elseif($type ==Wy){ $player =newWyPlayer();}elseif($type ==KG){ $player =newKGPlayer();}else{ $player =null;}return $player;}}// 业务代码修改如下 $player =MusicPlayerFactory:create(QQ); $player->on();// 打开播放器 $player->choiceMusic(我不配);// 选择歌曲 $player->play();// 开始播放 对于上面的简单工厂模式,如果我们需要添加新的音乐播放器,就一定会修改MusicPlayerFactory的create方法,这有点不符合“开闭原则”。对于这种条件分支不是很多,另外类的创建也非常的简单,使用简单工厂模式是完全可以的。如果非要将if分支逻辑去掉,使他符合“开闭原则”,那么就可以使用工厂方法来实现。对于工厂方法,也不是一定比简单工厂模式要好,虽然它的扩展性比较好,但是牺牲了可读性。 工厂方法模式 定义:在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 现在我们用“多态”来消除掉上面简单工厂模式的if分支结构。实现的代码如下所示: 复制interfaceIMusicPlayerFactory{staticfunction create ();}classQQPlayerFactoryimplementsIMusicPlayerFactory{publicstaticfunction create (){returnnewQQPlayer();}}classWyPlayerFactoryimplementsIMusicPlayerFactory{publicstaticfunction create (){returnnewWyPlayer();}}classKGPlayerFactoryimplementsIMusicPlayerFactory{publicstaticfunction create (){returnnewKGPlayer();}}// 业务代码修改如下if($type ==QQ){ $player =QQPlayerFactory::create();}elseif($type ==Wy){ $player =WyPlayerFactory::create();}elseif($type ==KG){ $player =KGPlayerFactory::create();}else{thrownew \\\\Exception(...);} $player->on();// 打开播放器 $player->choiceMusic(我不配);// 选择歌曲 $player->play();// 开始播放 可以看到,问题又回到了原点,业务代码里又出现了if条件分支结构。那么怎么去解决该问题呢? 我们可以为工厂类再创建一个简单工厂,用来创建工厂类对象。新的简单工厂代码如下: 复制classMusicPlayerFactoryMap{constPlayers=[QQ=>QQPlayerFactory,Wy=>WyPlayerFactory,KG=>KGPlayerFactory];publicstaticfunction getPlayerFactory (string $type){if(empty($type)){returnnull;}return(self::Players[$type])::create();}}// 业务代码修改如下 $palyer =MusicPlayerFactoryMap::getPlayerFactory(QQ) $player->on();// 打开播放器 $player->choiceMusic(我不配);// 选择歌曲 $player->play();// 开始播放 可以看到,使用了工厂模式,结构变的比之前复杂的多。如果来的创建实例过程复制,我们才会推荐使用工厂方法模式。 抽象工厂模式 抽象工厂模式使用场景比较特殊,用的比较少。在工厂方法模式中,具体工厂负责生产具体的产品,每一个工厂对应一个具体产品。但有时候,我们需要一个工厂可以创建多个产品对象,而不是一个单一的产品。 我们用一个例子来看看:对象电脑厂是负责生产电脑来出售的。我们知道,电脑是由主机、键盘、显示器以及鼠标组成的,目前对象电脑城只生产3种电脑,低配、中配和高配的,不同配置的电脑使用的主机品牌、显示器品牌等都是不同的。 主机目前有:麒麟主机、雷霆主机、冬日主机 键盘目前有:雷柏、罗技、雷蛇 显示器目前有:aoc、hkc、BenQ 鼠标目前有:罗技、灵蛇、方正 顶配版电脑由麒麟主机、雷柏键盘、aoc显示器、罗技鼠标组成,中配由……。 关于主机的代码如下: 复制interfaceHost{staticfunction createHost ();}classDrHostimplementsHost{publicstaticfunction createHost(){ echo 创建冬日主机. PHP_EOL;}}classQlHostimplementsHost{publicstaticfunction createHost(){ echo 创建麒麟主机. PHP_EOL;}}classLtHostimplementsHost{publicstaticfunction createHost(){ echo 创建雷霆主机. PHP_EOL;}} 类似的,去创建键盘、显示器、鼠标,代码这里就不贴了。 现在,我们定义一个创建电脑的接口。 复制interfaceComputerFactory{staticfunction createHost ();staticfunction createKeyboard ();staticfunction createMonitor ();staticfunction createMouse ();} 然后完成三个具体工厂用于创建低配、中配以及高配版电脑。 复制classGreatComputerFactoryimplementsComputerFactory{publicstaticfunction createHost(){QlHost::createHost();}publicstaticfunction createKeyboard(){LbKeyboard::createKeyboard();}publicstaticfunction createMonitor(){AocMonitor::createMonitor();}publicstaticfunction createMouse(){LjMouse::createMouse();}}classGoodComputerFactoryimplementsComputerFactory{publicstaticfunction createHost(){LtHost::createHost();}publicstaticfunction createKeyboard(){LjKeyboard::createKeyboard();}publicstaticfunction createMonitor(){HkcMonitor::createMonitor();}publicstaticfunction createMouse(){LsMouse::createMouse();}}classNormalComputerFactoryimplementsComputerFactory{publicstaticfunction createHost(){DrHost::createHost();}publicstaticfunction createKeyboard(){LsKeyboard::createKeyboard();}publicstaticfunction createMonitor(){BenqMonitor::createMonitor();}publicstaticfunction createMouse(){FzMouse::createMouse();}} 现在可以来创建具体的电脑了 复制classGreatComputer{publicfunction __construct(){ echo 高配电脑. PHP_EOL;GreatComputerFactory::createHost();GreatComputerFactory::createKeyboard();GreatComputerFactory::createMonitor();GreatComputerFactory::createMouse();}}classGoodComputer{publicfunction __construct(){ echo 中配电脑. PHP_EOL;GoodComputerFactory::createHost();GoodComputerFactory::createKeyboard();GoodComputerFactory::createMonitor();GoodComputerFactory::createMouse();}}classNormalComputer{publicfunction __construct(){ echo 低配电脑. PHP_EOL;NormalComputerFactory::createHost();NormalComputerFactory::createKeyboard();NormalComputerFactory::createMonitor();NormalComputerFactory::createMouse();}}
    上一页:一文谈谈JavaScript和ECMAScript的关系 下一页:一文读懂hell编程三剑客之一的ed命令
    全部评论(0)