谈谈关于 DI(依赖注入)、IOC(容器)、AOP(切面编程)的设计模式

谈谈关于 DI(依赖注入)、IOC(容器)、AOP(切面编程)的设计模式

话不多说,直接上代码

DI(依赖注入)

db = $db;
    }

    public function find()
    {
        $this->db->select();
    }
}

$user = new User(new DB());
$user->find();

IOC(容器)

log = $log;
    }

    public function index()
    {
        return $this->log->write();
    }
}

/**
 * [容器]
 *
 * @Author  leeprince:2020-02-26 12:49
 */
class Ioc
{
    protected $bindings = [];

    /**
     * [绑定到容器数组,并返回可创建实例化对象的闭包函数]
     *      可以继续完善[已升级到bind 方法]:支持绑定闭包,进行闭包判断,如果不是闭包则创建闭包,如果是则直接绑定
     *
     * @Author  leeprince:2020-02-26 12:51
     * @param $abstract 要绑定的抽象(标识) / 接口名
     *                  【注意 :要绑定的到容器数组中的类或者接口名,使用「类型提示」 的方式在类的构造函数中注入依赖项时,会根据构造函数参数并反射后继续实例化,所以该值不可以随便定义,否则报错。
     *                  所以建议该参数使用绑定的的类 / 接口名】
     * @param $concrete 绑定的类名 / 接口的实现类名
     */
    public function bindNoClosure($abstract, $concrete)
    {
        prt('[bind 方法]');

        if (is_null($concrete)) {
            $concrete = $abstract;
        }
        // 绑定闭包
        $this->bindings[$abstract]['concrete'] = function ($ioc) use ($concrete) {
            prt('bindings:'.$concrete);

            return $ioc->build($concrete);
        };

    }

    /**
     * [绑定到容器数组,并返回可创建实例化对象的闭包函数]
     *
     * @Author  leeprince:2020-03-08 15:34
     * @Author  leeprince:2020-02-26 12:51
     * @param $abstract 要绑定的抽象(标识) / 接口名
     * @param $concrete 绑定的类名 / 接口的实现类名 / 闭包 / null(绑定自身)
     */
    public function bind($abstract, $concrete = null)
    {
        prt('[bind 方法]');

        if (is_null($concrete)) {
            $concrete = $abstract;
        }

        if (! $concrete instanceof Closure) {
            $concrete =  $this->getClosure($abstract, $concrete);
        }


        // 绑定闭包
        $this->bindings[$abstract]['concrete'] = $concrete;
    }

    /**
     * [执行闭包函数,创建实例化对象]
     *
     * @Author  leeprince:2020-02-26 13:05
     * @param $abstract
     * @return mixed
     */
    public function make($abstract)
    {
        $ioc = $this->bindings[$abstract]['concrete'];
        prt('[make]-$abstract:'.$abstract);
        // prt(debug_backtrace());
        return $ioc($this);
    }

    /**
     * [获取闭包函数]
     *
     * @Author  leeprince:2020-03-09 23:01
     * @param $abstract
     * @param $concrete
     * @return Closure
     */
    public function getClosure($abstract, $concrete)
    {
        return function ($ioc, $parameters = []) use ($abstract, $concrete) {
            return $ioc->build($concrete);
        };
    }

    /**
     * [通过反射类获取实例(创建对象)]
     *
     * @Author  leeprince:2020-02-26 12:57
     * @param $concrete
     */
    public function build($concrete)
    {
        // 使用反射类反射出当前类的所有信息
        $reflection = new ReflectionClass($concrete);
        prt('[build]-$concrete:'.$concrete);

        // 判断是否可以实例化
        if (!$reflection->isInstantiable()) {
            throw new Exception('该类无法实例化', 1);
        }

        // 获取构造函数
        $constructor = $reflection->getConstructor();
        if (is_null($constructor)) {
            // 实例化对象
            return $reflection->newInstance();
        } else {
            // 获取构造函数的参数
            $depenen = $constructor->getParameters();
            $instences = $this->getDependencies($depenen);
            return $reflection->newInstanceArgs($instences);
        }

    }

    /**
     * [根据构造函数中的类型提示参数(依赖注入)中继续实例化对象]
     *
     * @Author  leeprince:2020-02-26 22:54
     * @param array $depenen
     * @return array
     */
    protected function getDependencies(array $depenen)
    {
        $depenencies = [];
        prt($depenen,  '[getDependencies]-参数$depenen:');
        foreach ($depenen as $parameter) {
            prt($parameter->getClass(), '[getDependencies]-$parameter->getClass():');
            prt($parameter->getClass()->name, '[getDependencies]-$parameter->getClass()->name:');

            $depenencies[] = $this->make($parameter->getClass()->name);
        }
        prt($depenencies, '[getDependencies]-$depenencies:');

        return $depenencies;
    }
}

// 实例化容器
$ioc = new Ioc();

// 绑定自身
$ioc->bind('DbLog', 'DbLog');
$ioc->bind('FileLog', 'FileLog');
$log = $ioc->make('FileLog'); // // $log = $ioc->make('DbLog');
echo $log->write();

// 绑定闭包
$ioc->bind('DbLog', function($ioc) {
   return new DbLog();
});
$log = $ioc->make('DbLog');
echo $log->write();

// 绑定接口到实现
$ioc->bind('iLog', 'DbLog'); // $ioc->bind('iLog', 'FileLog');
$ioc->bind('logger', 'Logger');
$logger = $ioc->make('logger');
echo $logger->index();



function prt($data, $msg = '')
{
    if (!IS_DEBUG) {
        echo '
';
        echo $msg;
        print_r($data);
    }
}

AOP(切面编程)

name = $name;
    }

    /**
     * [Description]
     *
     * @Author  leeprince:2020-02-28 17:14
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }
}


/**
 * [sesssion 缓存]
 *
 * @Author  leeprince:2020-02-28 17:14
 */
class FileCache
{
    protected $name;

    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * [Description]
     *
     * @Author  leeprince:2020-02-28 17:14
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }
}

/**
 * [AOP 切面缓存类]
 *
 * @Author  leeprince:2020-02-28 17:17
 */
class Cache
{
    protected $obj;

    public function __construct($obj)
    {
        $this->obj = $obj;
    }

    public function __call($method, $args)
    {
        var_dump("method:{{$method}}--args:".json_encode($args));
        return call_user_func_array([$this->obj, $method], $args);
    }
}

$sessionCache = new Cache(new SessionCache());
$sessionCache->setName('leeprince');
var_dump($sessionCache->getName());

源码地址

https://github.com/leeprince/my_pattern/tree/master/di_ioc_aop

你可能感兴趣的:(谈谈关于 DI(依赖注入)、IOC(容器)、AOP(切面编程)的设计模式)