Ioc实现的基本机制

复制代码
<?php

interface KeyBoard{
    public function make();
}

interface Mouse{
    public function make();
}

class MechanicalKeyboard implements KeyBoard
{
    public function make(){
        echo '机械键盘正在work';
    }
}

class CommonKeyboard implements KeyBoard
{
    public function make(){
        echo '普通键盘正在work';
    }
}

class CommonMouse implements Mouse
{
    public function make(){
        echo '普通鼠标正在work';
    }
}


class Computer
{
    protected $keyBoard;

    protected $mouse;

    public function __construct(KeyBoard $keyBoard,Mouse $mouse)
    {
        $this->keyBoard = $keyBoard;

        $this->keyBoard->make();

        $this->mouse = $mouse;

        $this->mouse->make();
    }
}

class Container
{
    private $binds;

    //将接口和类名保存到binds中
    public function bind($contract,$concrete)
    {
        $this->binds[$contract] = $concrete;
    }

    //获取到指定方法的注入参数,默认方法是采用__construct进行注入
    public function methodBindParams($className)
    {
        $reflect = new Reflect($className,'__construct');

        return $reflect->bindParamsToMethod();
    }

    //实例化类
    public function make($className)
    {
        //获取需要实例化类所需要的必要参数
        $methodBindParams = $this->methodBindParams($className);

        //实例化类反射类
        $reflect = new Reflect($className,'__construct');

        //实例化类,插入实例化所需要的参数和参数接口对应的类
        return $reflect->make($this->binds,$methodBindParams);
    }
}

class Reflect
{
    private $className;

    private $methodName;

    public function __construct($className,$methodName)
    {
        $this->className = $className;

        $this->methodName = $methodName;
    }

    public function bindParamsToMethod()
    {
        $params = [];

        //获取到类的方法信息
        $method = new ReflectionMethod($this->className,$this->methodName);

        //将类方法参数信息保存到params中
        foreach ($method->getParameters() as $param){
            $params[] = [
                //参数名称
                $param->name,
                //参数是哪个类型
                $param->getClass()->name
            ];
        }

        //返回这个类--》方法的参数
        return [$this->className => $params];
    }

    public function make($bind,$methodBindParams)
    {
        $args = [];

        //遍历类-》参数列表
        foreach ($methodBindParams as $className => $params){
            //遍历参数列表
            foreach ($params as $param){
                //获取到参数名和参数类型(是哪个接口)
                list($paramName,$paramType) = $param;

                //实例化对应接口的实现的类
                $paramName = new $bind[$paramType]();

                //将实例化后的类放到args列表中
                array_push($args,$paramName);
            }
        }

        //实例化反射
        $reflectionClass = new ReflectionClass($this->className);

        //从给定参数生成一个实例
        return $reflectionClass->newInstanceArgs($args);
    }
}

$container = new Container();

$container->bind('KeyBoard','CommonKeyBoard');
$container->bind('Mouse','CommonMouse');

$container->make('Computer');
复制代码

 

posted @   易文杰  阅读(170)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示