最新公告
  • 欢迎您光临立业阁,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 一文读懂简单工厂、工厂方法、抽象工厂_php教程

  • 正文概述
  • 评价建议

  • 简单工厂模式

    基本上每个人手机里都有一款音乐播放器,目前流行的播放器有: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 (empty($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();
        }
    }

    以上就是一文读懂简单工厂、工厂方法、抽象工厂的详细内容,更多请关注liyege.cn其它相关文章!

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    • 1175会员总数(位)
    • 111858资源总数(个)
    • 2本周发布(个)
    • 0 今日发布(个)
    • 246稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情
    冀ICP备19022365号-1 百度地图

    侵权联系邮箱[email protected]

    立业阁(www.liyege.cn)免费提供wordpress主题模板、dedecms模板、帝国cms模板、小说网站源码、电影网站源码以及网络技术分享,建站源码,小说模板,电影模板,网赚教程,VPS推荐