【php】简单工厂模式、依赖注入

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:37   1665   0

业务场景:我们每天需要准时到公司上班下班,可以搭乘不同交通工具。

在不使用设计模式时,通常可以这样写:

//通勤
class Commute{

    //上班
    public function gotowork(){
        switch ($way) {
            case 'bus':
                return '乘坐巴士上班';
            default:
                return '乘坐地铁上班';
        }
    }
    //下班
    public function gohome(){
        switch ($way) {
            case 'bus':
                return '乘坐巴士下班';
            default:
                return '乘坐地铁下班';
        }
    }
}

以后需要新增通勤方式、修改某种通勤方式,都需要修改Commute类,此类的维护随着业务增加变得复杂。

由此引入工厂模式:

不管使用简单工厂模式还是依赖注入,我们首先需要定义交通工具。

1.定义交通工具接口、类

//交通工具
interface Vehicle{

    function travel();
}

//巴士
class Bus implements Vehicle{

    public function travel(){
        return "巴士";
    }
}

//地铁
class Metro implements Vehicle{

    public function travel(){
        return "地铁";
    }
}

2.一个生产乘坐不同交通方式的工厂

//普通工厂模式
class Factory{

    //通勤方案:根据交通方式返回不同的对象
    public function mychoice($way){
        switch ($way) {
            case 'bus':
                return new Bus;
            default:
                return new Metro;
        }
    }

}

3.调用工厂类实现出行

class Commute{

    //此时我上班通勤方式只需修改传入Factory的参数即可更改
    public function gotowork(){
        return '乘坐'.(new Factory)->mychoice('bus')->travel().'上班</br>';
    }

    public function gohome(){
        return '乘坐'.(new Factory)->mychoice('bus')->travel().'下班</br>';
    }
}

Commute只需关注要乘坐bus上班,不关心bus具体实现。

echo (new Commute)->gotowork();

引入工厂模式后,新增、修改都给了工厂,用户出行变得简洁。

但是新增、修改仍然需要修改工厂类,此时引入依赖注入。

以上步骤1定义交通工具接口、类仍然有用,第2步之后变为:

//通勤
class Commute{

    private $way;

    //Vehicle的意思是定义强类型:在此处的参数$car必须是遵从Vehicle契约的对象实例。如果这里参数类型强制是一个类的话,代表的是参数必须是类的实例或者是该类子类的实例
    public function __construct(Vehicle $car){
        $this->way = $car;
    }
    //此时我上班通勤方式只需修改传入Factory的参数即可更改
    public function gotowork(){
        return '乘坐'.$this->way->travel().'上班</br>';
    }

    public function gohome(){
        return '乘坐'.$this->way->travel().'下班</br>';
    }
}

Commute不再关心具体交通工具,只关心自己要乘坐交通工具上班,在调用时传入交通工具bus:

echo (new Commute(new Bus))->gotowork();

依赖注入解决了对工厂类的解耦,但是当后期需要更换增加新的交通方式,交通工具类依然需要修改、增加,此时可以引入IOC容器

IOC容器

以laravel为例,它的服务容器本身是一个类,在程序执行前用户可以通过匿名函数将自己的依赖关系绑定到容器,等程序真正运行时,容器可以通过反射递归地解析当前类的依赖、它的依赖的依赖并加载到容器中运行,简而言之,容器是可以注册各种接口并实现绑定的空间。这样做是为了最大程度地对依赖关系解耦。

在laravel中,这个依赖关系写在\config\app.php中,它通常获取的是.env文件中的配置参数。

反射是非常重要的概念,很多语言都有,在我看来它有一些旁观者的感觉,抓来一个类、对象都可以对其分析、构建,而不用真的引用它、运行它才可以。

有说法是反射会带来性能的一定损失,我没有测试过无法下定论,不过对于laravel这样的框架来说,优雅才是第一位的,它首先要提高的是开发效率,要让代码更加整洁、扩展性更强。

https://www.php.net/manual/zh/book.reflection.php

https://learnku.com/docs/laravel-core-concept/5.5/依赖注入,控制翻转,反射/3017

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP