談?wù)勱P(guān)于 DI(依賴注入)怨咪、IOC(容器)、AOP(切面編程)的設(shè)計(jì)模式

談?wù)勱P(guān)于 DI(依賴注入)村生、IOC(容器)惊暴、AOP(切面編程)的設(shè)計(jì)模式

話不多說饼丘,直接上代碼

DI(依賴注入)

<?php
/**
 * [DI - 依賴注入
 *      原則:應(yīng)用的方法中不負(fù)責(zé)查找資源或者不負(fù)責(zé)查找其他依賴的協(xié)作對(duì)象, 而是通過參數(shù)趁桃,動(dòng)態(tài)的向該方法提供其他所需要的對(duì)象。DI 是IOC 的具體表現(xiàn)肄鸽,而IOC 不是一種設(shè)計(jì)模式而是一種思想
 * ]
 *
 * @Author  leeprince:2020-02-25 14:34
 */
class DB
{
    public function select()
    {
        echo '查詢數(shù)據(jù)庫連接對(duì)象';
    }
}

class User
{
    protected $db;

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

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

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

IOC(容器)

<?php
/**
 * [Ioc - 控制反轉(zhuǎn) - 容器
 *      概念:將設(shè)計(jì)好的對(duì)象及對(duì)象的依賴關(guān)系交給容器管理卫病,而不是傳統(tǒng)的直接在應(yīng)用組件內(nèi)部直接控制
 *      步驟3:
 *          1. 【綁定】定義接口和實(shí)現(xiàn)類,并將對(duì)象綁定到容器數(shù)組典徘,并返回可創(chuàng)建實(shí)例化對(duì)象的閉包函數(shù)
 *          2. 【反射】在返回的閉包函數(shù)中蟀苛,根據(jù)反射機(jī)制(反射類)將要實(shí)例對(duì)象的構(gòu)造函數(shù)反射出來,并根據(jù)構(gòu)造函數(shù)是否包含參數(shù)返回實(shí)例對(duì)象
 *          3. 【執(zhí)行】執(zhí)行閉包函數(shù)逮诲,通過反射類獲取實(shí)例對(duì)象
 * ]
 *
 * @Author  leeprince:2020-02-26 12:28
 */
define('IS_DEBUG', true);

/**
 * [日志接口]
 *
 * @Author  leeprince:2020-02-26 12:41
 */
interface iLog
{
    public function write();
}

/**
 * [實(shí)現(xiàn)文件日志]
 *
 * @Author  leeprince:2020-02-26 12:41
 */
class FileLog implements iLog
{
    public function write()
    {
        return '已記錄文件日志';
    }
}

/**
 * [實(shí)現(xiàn)數(shù)據(jù)庫日志]
 *
 * @Author  leeprince:2020-02-26 12:41
 */
class DbLog implements iLog
{
    public function write()
    {
        return '已記錄數(shù)據(jù)庫日志';
    }
}

/**
 * [根據(jù)依賴注入的實(shí)例來記錄日志]
 *
 * @Author  leeprince:2020-02-26 12:47
 */
class Logger
{
    protected $log;

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

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

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

    /**
     * [綁定到容器數(shù)組帜平,并返回可創(chuàng)建實(shí)例化對(duì)象的閉包函數(shù)]
     *      可以繼續(xù)完善[已升級(jí)到bind 方法]:支持綁定閉包,進(jìn)行閉包判斷梅鹦,如果不是閉包則創(chuàng)建閉包裆甩,如果是則直接綁定
     *
     * @Author  leeprince:2020-02-26 12:51
     * @param $abstract 要綁定的抽象(標(biāo)識(shí)) / 接口名
     *                  【注意 :要綁定的到容器數(shù)組中的類或者接口名,使用「類型提示」 的方式在類的構(gòu)造函數(shù)中注入依賴項(xiàng)時(shí)齐唆,會(huì)根據(jù)構(gòu)造函數(shù)參數(shù)并反射后繼續(xù)實(shí)例化嗤栓,所以該值不可以隨便定義,否則報(bào)錯(cuò)箍邮。
     *                  所以建議該參數(shù)使用綁定的的類 / 接口名】
     * @param $concrete 綁定的類名 / 接口的實(shí)現(xiàn)類名
     */
    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);
        };

    }

    /**
     * [綁定到容器數(shù)組茉帅,并返回可創(chuàng)建實(shí)例化對(duì)象的閉包函數(shù)]
     *
     * @Author  leeprince:2020-03-08 15:34
     * @Author  leeprince:2020-02-26 12:51
     * @param $abstract 要綁定的抽象(標(biāo)識(shí)) / 接口名
     * @param $concrete 綁定的類名 / 接口的實(shí)現(xiàn)類名 / 閉包 / 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;
    }

    /**
     * [執(zhí)行閉包函數(shù),創(chuàng)建實(shí)例化對(duì)象]
     *
     * @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);
    }

    /**
     * [獲取閉包函數(shù)]
     *
     * @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);
        };
    }

    /**
     * [通過反射類獲取實(shí)例(創(chuàng)建對(duì)象)]
     *
     * @Author  leeprince:2020-02-26 12:57
     * @param $concrete
     */
    public function build($concrete)
    {
        // 使用反射類反射出當(dāng)前類的所有信息
        $reflection = new ReflectionClass($concrete);
        prt('[build]-$concrete:'.$concrete);

        // 判斷是否可以實(shí)例化
        if (!$reflection->isInstantiable()) {
            throw new Exception('該類無法實(shí)例化', 1);
        }

        // 獲取構(gòu)造函數(shù)
        $constructor = $reflection->getConstructor();
        if (is_null($constructor)) {
            // 實(shí)例化對(duì)象
            return $reflection->newInstance();
        } else {
            // 獲取構(gòu)造函數(shù)的參數(shù)
            $depenen = $constructor->getParameters();
            $instences = $this->getDependencies($depenen);
            return $reflection->newInstanceArgs($instences);
        }

    }

    /**
     * [根據(jù)構(gòu)造函數(shù)中的類型提示參數(shù)(依賴注入)中繼續(xù)實(shí)例化對(duì)象]
     *
     * @Author  leeprince:2020-02-26 22:54
     * @param array $depenen
     * @return array
     */
    protected function getDependencies(array $depenen)
    {
        $depenencies = [];
        prt($depenen,  '[getDependencies]-參數(shù)$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;
    }
}

// 實(shí)例化容器
$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();

// 綁定接口到實(shí)現(xiàn)
$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 '<pre>';
        echo $msg;
        print_r($data);
    }
}

AOP(切面編程)

<?php
/**
 * [AOP - 切面編程
 *      把去要調(diào)用的重復(fù)代碼提前抽離出來锭弊,然后注入到需要的業(yè)務(wù)執(zhí)行里面
 * ]
 *
 * @Author  leeprince:2020-02-26 12:28
 */


/**
 * [sesssion 緩存]
 *
 * @Author  leeprince:2020-02-28 17:14
 */
class SessionCache
{
    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;
    }
}


/**
 * [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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末堪澎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子味滞,更是在濱河造成了極大的恐慌樱蛤,老刑警劉巖马昙,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異刹悴,居然都是意外死亡行楞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門土匀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來子房,“玉大人,你說我怎么就攤上這事就轧≈ず迹” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵妒御,是天一觀的道長(zhǎng)解愤。 經(jīng)常有香客問我,道長(zhǎng)乎莉,這世上最難降的妖魔是什么送讲? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮惋啃,結(jié)果婚禮上哼鬓,老公的妹妹穿的比我還像新娘。我一直安慰自己边灭,他們只是感情好异希,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绒瘦,像睡著了一般称簿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惰帽,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天憨降,我揣著相機(jī)與錄音,去河邊找鬼善茎。 笑死券册,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的垂涯。 我是一名探鬼主播烁焙,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼耕赘!你這毒婦竟也來了骄蝇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤操骡,失蹤者是張志新(化名)和其女友劉穎九火,沒想到半個(gè)月后赚窃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岔激,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年勒极,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虑鼎。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辱匿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炫彩,到底是詐尸還是另有隱情匾七,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布江兢,位于F島的核電站昨忆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杉允。R本人自食惡果不足惜邑贴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夺颤。 院中可真熱鬧痢缎,春花似錦胁勺、人聲如沸世澜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寥裂。三九已至,卻和暖如春案疲,著一層夾襖步出監(jiān)牢的瞬間封恰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工褐啡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诺舔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓备畦,卻偏偏與公主長(zhǎng)得像低飒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子懂盐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容