Blogger Information
Blog 8
fans 0
comment 0
visits 7320
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
5.28 谈谈对容器注入的理解以及门面Facade的认识
Allen的php博客
Original
886 people have browsed it

在实现用户登录功能时,使用普通的new对象方法使工作类(User)对工具类(Db,Validate,View)产生了严重的依赖关系及耦合问题。虽然可以使用依赖注入解决耦合问题,但必须要对工具类的方法或参数了解,很容易造成意想不到的问题出现。

容器注入可以最大限度的简化外部对象调用,即创建容器、服务注册、容器依赖,但容器依赖必须使用User()工作类进行调用,灵活性不高。因此使用facade门面外观模式与容器注入相结合,即对调用者来说,他不需要事先知道工作类(User)中具体操作是哪个类中,只需要调用Facade即可完成操作,并且facade门面静态化方法较纯容器注入代码执行效率更高。

实例代码如下:

〓 依赖容器

◇ 创建Demo1.php:普通的new对象方法

<?php

/**

* 用户登录

* 1. 涉及到三个操作:链接数据、数据验证、模板输出

* 2. 创建三个类:Db,validate,view:这三个类是工具类

* 3. User类负责调用工具类,实现用户登录:是工作类

*/

//数据库链接类

class Db

{

//数据连接

public function connect()

{

return '数据库链接成功!<br>';

}

}


//数据验证类

class Validate

{

//数据验证

public function check()

{

return '数据验证成功!<br>';

}

}


//视图类

class View

{

//内容输出

public function display()

{

return '用户登录成功!<br>';

}

}



//用户类:工作类

class User

{

//登录操作

public function login()

{

//实例化Db类,并调用connect()方法,连接数据库

$db = new Db();

echo $db->connect();


//实例化Validate类,并调用check()方法,验证数据

$validate = new Validate();

echo $validate->check();


//实例化View类,并调用display()方法,完成用户登录

$view = new View();

echo $view->display();


}

}


//客户端进行调用

//实例化User类

$user = new User();

echo $user->login();



//工作类User对三个工具类:Db,Validate,View产生了严重的依赖,并且要求不仅要对User类熟悉,还要对工具类十分了解,这种耦合如何解耦?



◇ 创建Demo2.php:依赖注入解耦


<?php

/**

 * 使用依赖注入来进行解耦:DI

 * 对工具类(Db,Validate,View)的实例化不要在工作类(User)中完成,应在客户端完成

 * 在工作类中必须要有接收器,来保存工具类的实例

 * 将工作类依赖的对象,以方法参数的方式注入到当前的类中

 */


//数据库链接类

class Db

{

//数据连接

public function connect()

{

return '数据库链接成功!<br>';

}

}


//数据验证类

class Validate

{

//数据验证

public function check()

{

return '数据验证成功!<br>';

}

}


//视图类

class View

{

//内容输出

public function display()

{

return '用户登录成功!<br>';

}

}



//用户类:工作类

class User

{

//创建三个接收器,成员属性

protected $db = null; //保存数据对象

protected $validate = null; //保存数据验证对象

protected $view = null; //保存视图对象


//登录操作

public function login(Db $db, Validate $validate, View $view)

{

//实例化Db类,并调用connect()方法,连接数据库

echo $db->connect();


//实例化Validate类,并调用check()方法,验证数据

echo $validate->check();


//实例化View类,并调用display()方法,完成用户登录

echo $view->display();


}

}


//客户端进行调用

//将工具类在客户端全部实例化

$db = new Db();

$validate = new Validate();

$view = new View();


////实例化User类

$user = new User();

echo '<h2>用依赖注入完成解耦</h2>';

echo $user->login($db,$validate,$view);


/**

 * 依赖注入仍然要求在客户端进行类的实例化

 * 遗留问题:还是无法解决对工具类需要十分了解的问题

 * 期望:能不能把这个调用者的实例化过程也省略掉,我们只要给出一个类名,以及如何去实例化这个类就可以了,其他工作一概不管

 * 解决办法:用容器来实现统一注入,文件在Demo3.php

 */


◇ 创建Demo3.php:容器依赖解耦


<?php

/**

 * 容易:也叫服务容器(IOC)

 * 基本思路:拿来就用,最大限度简化外部对象调用,类似于 即插即用

 * 基本实现分三步:

 * 1. 创建容器:本质就是将一个类与他的实现绑定到一个关联数组;

 * 2. 服务注册:初始化这个关联数组,将工具类绑定到容器中;

 * 3. 容器依赖:也叫依赖容器,调用的时候直接传一个容器对象,不用再一个一个传具体对象

 */


//数据库链接类

class Db

{

//数据连接

public function connect()

{

return '数据库链接成功!<br>';

}

}


//数据验证类

class Validate

{

//数据验证

public function check()

{

return '数据验证成功!<br>';

}

}


//视图类

class View

{

//内容输出

public function display()

{

return '用户登录成功!<br>';

}

}


//1. 创建容器

class Container

{

//创建一个空数组,用来保存工具类及实现方法

protected $instance = [];


//将需要实例化的类与它的实现方法进行绑定

public function bind($abstract, Closure $process)

{

$this->instance[$abstract] = $process;

}


//创建特定类的实例

public function make($abstract, $process=[])

{

return call_user_func_array($this->instance[$abstract], []); //执行对象方法

}


}


//2. 服务注册:就是调用容器的bind()将对象(对象===实例)注册到容器中

$container = new Container();


//将Db类绑定到容器中

$container->bind('Db', function(){

return new Db();

});


//将Validate类绑定到容器中

$container->bind('Validate', function(){

return new Validate();

});


//将View类绑定到容器中

$container->bind('View', function(){

return new View();

});


// var_dump($container->instance);die(); //查看容器的instance属性,测试是否成功


//3. 容器依赖:所有用到的对象,以容器的方式,注入到当前的工作类中

//用户类:工作类

class User

{

public function login(Container $container)

{

//$container->make('Db')实例化Db类创建Db对象

echo $container->make('Db')->connect();

echo $container->make('Validate')->check();

echo $container->make('View')->display();

}

}


//控制台调用方法

$user = new User();

echo '<h2>用依赖容器实现解耦</h2>';

echo $user->login($container);


//问题遗留:容器依赖必须使用User()工作类进行调用,我们用facade门面模式进行简化,见Demo4.php



〓 Facade门面外观模式



◇ 创建Demo4.php和Container.php:容器依赖结合facade解耦


Demo4.php-----------------------------------------------------


<?php

/**

 * facade:门面模式,也叫外观模式

 * 就是将一些操作进行封装,对外提供一个统一的接口

 * facade模式与容器依赖是黄金搭档

 */

require 'Container.php'; //导入容器


/**

 * Facade类实现三个功能

 * 1. 链接数据库

 * 2. 数据验证

 * 3. 输出提示

 * 对于调用者来说,他不需要实现知道这三个操作在哪个具体的类中,他只需要调用Facade就可以执行以上三个操作

 */


class Facade

{

// 1. 链接数据库

public static function connect(Container $container)

{

return $container->make('Db')->connect();

}


// 2. 数据验证

public static function check(Container $container)

{

return $container->make('Validate')->check();

}


// 3. 输出提示

public static function display(Container $container)

{

return $container->make('View')->display();

}


}


//客户端调用

echo '<h2>用facade门面外观模式统一调用User类</h2>';

echo Facade::connect($container);

echo Facade::check($container);

echo Facade::display($container);


Container.php----------------------------------------------------


<?php

/**

 * 容易:也叫服务容器(IOC)

 * 基本思路:拿来就用,最大限度简化外部对象调用,类似于 即插即用

 * 基本实现分三步:

 * 1. 创建容器:本质就是将一个类与他的实现绑定到一个关联数组;

 * 2. 服务注册:初始化这个关联数组,将工具类绑定到容器中;

 * 3. 容器依赖:也叫依赖容器,调用的时候直接传一个容器对象,不用再一个一个传具体对象

 */


//数据库链接类

class Db

{

//数据连接

public function connect()

{

return '数据库链接成功!<br>';

}

}


//数据验证类

class Validate

{

//数据验证

public function check()

{

return '数据验证成功!<br>';

}

}


//视图类

class View

{

//内容输出

public function display()

{

return '用户登录成功!<br>';

}

}


//1. 创建容器

class Container

{

//创建一个空数组,用来保存工具类及实现方法

protected $instance = [];


//将需要实例化的类与它的实现方法进行绑定

public function bind($abstract, Closure $process)

{

$this->instance[$abstract] = $process;

}


//创建特定类的实例

public function make($abstract, $process=[])

{

return call_user_func_array($this->instance[$abstract], []); //执行对象方法

}


}


//2. 服务注册:就是调用容器的bind()将对象(对象===实例)注册到容器中

$container = new Container();


//将Db类绑定到容器中

$container->bind('Db', function(){

return new Db();

});


//将Validate类绑定到容器中

$container->bind('Validate', function(){

return new Validate();

});


//将View类绑定到容器中

$container->bind('View', function(){

return new View();

});



◇ 创建Demo5.php: 进一步简化facade门面外观模式


<?php

/**

 * facade门面外观模式简化

 * 

 */

require 'Container.php'; //导入容器


class Facade

{

//保存容器对象

protected static $container = null;


//创建初始化方法,给容器对象赋值

public static function initalize(Container $container)

{

static::$container = $container;

}


// 1. 链接数据库

public static function connect()

{

return static::$container->make('Db')->connect();

}


// 2. 数据验证

public static function check()

{

return static::$container->make('Validate')->check();

}


// 3. 输出提示

public static function display()

{

return static::$container->make('View')->display();

}


}


//客户端调用

echo '<h2>简化了的facade门面外观模式调用</h2>';

Facade::initalize($container);

echo Facade::connect();

echo Facade::check();

echo Facade::display();


Correction status:Uncorrected

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!