PHP解耦的三重境界(浅谈服务容器)


Posted in PHP onMarch 13, 2017

阅读本文之前你需要掌握:PHP语法,面向对象

在完成整个软件项目开发的过程中,有时需要多人合作,有时也可以自己独立完成,不管是哪一种,随着代码量上升,写着写着就“失控”了,渐渐“丑陋接口,肮脏实现”,项目维护成本和难度上升,到了难以维持的程度,只有重构或者重新开发。

第一重境界

假设场景:我们需要写一个处理类,能够同时操作会话,数据库和文件系统。我们或许会这么写。

境界特征:可以运行,但是严重耦合

class DB{
 public function DB($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class FileSystem{
 public function FileSystem($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class Session{
 public function Session($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class Writer{
 public function Write(){
 $db=new DB(1,2);
 $filesystem=new FileSystem(3,4);
 $session=new Session(5,6);
 }
}
$writer=new Writer();
$writer->write();

写法缺点:

1.在公有函数中构造对象,一旦涉及到如数据库参数的变动,修改会有很大的工作量

2.负责设计Writer类的人员需要对DB等类的各种API要熟悉

有没有办法降低耦合度?

第二重境界(参数依赖)

假设场景:数据库地址因为客户不同,需要经常更换,调用到DB的类很多(假如有几十个),希望即使更改了数据库地址,也不用去修改这些类的代码。

class DB{
 public function DB($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class FileSystem{
 public function FileSystem($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class Session{
 public function Session($arg1,$arg2){
 echo 'constructed!'.PHP_EOL;
 }
}
class Writer{
 protected $_db;
 protected $_filesystem;
 protected $_session;
 public function Set($db,$filesystem,$session){
 $this->_db=$db;
 $this->_filesystem=$filesystem;
 $this->_session=$session;
 }
 public function Write(){

 }
}
$db=new DB(1,2);
$filesystem=new FileSystem(3,4);
$session=new Session(5,6);
$writer=new Writer();
$writer->Set($db,$filesystem,$session);
$writer->write();

虽然把DB类的构造移到了客户端,一旦涉及修改,工作量大大降低,但是新问题来了:为了创建一个Writer类,我们需要先创建好DB类,FileSystem类等,这对负责涉及Writer类的人来说,要求是很高的,他需要看很多其他类文档,一个个创建(可能还需要初始化),然后才能创建出他要的writer变量。

所以,我们希望,能有一种更好的写法,使得写Writer类的人,用一种更加快捷的接口,就能创建和调用他要的类,甚至连参数都不用填。

第三重境界(IOC容器)

经过前两重境界,我们希望能新增以下这些好处:

1.希望DB类,Session类,FileSystem类“拿来即用”,不用每次繁琐的初始化,比如写$db=new DB(arg1,arg2);这类语句。

2.希望DB等类型的对象是“全局”,在整个程序运行期间,随时可以调用。

3.调用DB等类型的程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。

能够实现以上目标的就是IOC容器,可以把IOC容器简单的看成一个全局变量,并用关联数组把字符串和构造函数做绑定。

我们先实现一个容器类

class Container{
 public $bindings;
 public function bind($abstract,$concrete){
 $this->bindings[$abstract]=$concrete;
 }
 public function make($abstract,$parameters=[]){
 return call_user_func_array($this->bindings[$abstract],$parameters);
 }
}

服务注册(绑定)

$container=new Container();
$container->bind('db',function($arg1,$arg2){
 return new DB($arg1,$arg2);
});
$container->bind('session',function($arg1,$arg2){
 return new Session($arg1,$arg2);
});
$container->bind('fs',function($arg1,$arg2){
 return new FileSystem($arg1,$arg2);
});

容器依赖

class Writer{
 protected $_db;
 protected $_filesystem;
 protected $_session;
 protected $container;
 public function Writer(Container $container){
 $this->_db=$container->make('db',[1,2]);
 $this->_filesystem=$container->make('session',[3,4]);
 $this->_session=$container->make('fs',[5,6]);
 }
}
$writer=new Writer($container);

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

PHP 相关文章推荐
全文搜索和替换
Oct 09 PHP
php+mysql 实现身份验证代码
Mar 24 PHP
通过JavaScript或PHP检测Android设备的代码
Mar 09 PHP
PHP操作数组的一些函数整理介绍
Jul 17 PHP
采用PHP函数memory_get_usage获取PHP内存清耗量的方法
Dec 06 PHP
浅析php中json_encode()和json_decode()
May 25 PHP
ThinkPHP表单自动验证实例
Oct 13 PHP
Symfony2框架创建项目与模板设置实例详解
Mar 17 PHP
laravel自定义分页效果
Jul 23 PHP
PHP 传输会话curl函数的实例详解
Sep 12 PHP
PHP操作Postgresql封装类与应用完整实例
Apr 24 PHP
laravel框架实现去掉URL中index.php的方法
Oct 12 PHP
PHP控制反转(IOC)和依赖注入(DI)
Mar 13 #PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
Mar 13 #PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
Mar 13 #PHP
php解析mht文件转换成html的实例
Mar 13 #PHP
使用phpQuery获取数组的实例
Mar 13 #PHP
php获取linux命令结果的实例
Mar 13 #PHP
老生常谈PHP位运算的用途
Mar 12 #PHP
You might like
开启CURL扩展,让服务器支持PHP curl函数(远程采集)
2011/03/19 PHP
php实现给图片加灰色半透明效果的方法
2014/10/20 PHP
一个完整的PHP类包含的七种语法说明
2015/06/04 PHP
Symfony查询方法实例小结
2017/06/28 PHP
PHP PDOStatement::columnCount讲解
2019/01/30 PHP
javascript 中对象的继承〔转贴〕
2007/01/22 Javascript
js实现简单模态窗口,背景灰显
2008/11/14 Javascript
JavaScript在IE中“意外地调用了方法或属性访问”
2008/11/19 Javascript
jquery禁止输入数字以外的字符的示例(纯数字验证码)
2014/04/10 Javascript
JavaScript知识点总结(十)之this关键字
2016/05/31 Javascript
JS实现JSON.stringify的实例代码讲解
2017/02/07 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
react中的ajax封装实例详解
2017/10/17 Javascript
javascript Function函数理解与实战
2017/12/01 Javascript
vue引入新版 vue-awesome-swiper插件填坑问题
2018/01/25 Javascript
微信小程序实现星星评分效果
2020/11/01 Javascript
[02:20]DOTA2亚洲邀请赛 IG战队出场宣传片
2015/02/07 DOTA
Python中几种操作字符串的方法的介绍
2015/04/09 Python
python中string模块各属性以及函数的用法介绍
2016/05/30 Python
对Pandas DataFrame缺失值的查找与填充示例讲解
2018/11/06 Python
Python pandas.DataFrame调整列顺序及修改index名的方法
2019/06/21 Python
使用pytorch搭建AlexNet操作(微调预训练模型及手动搭建)
2020/01/18 Python
tensorflow2.0的函数签名与图结构(推荐)
2020/04/28 Python
Html5与App的通讯方式详解
2019/10/24 HTML / CSS
优衣库澳大利亚官网:UNIQLO澳大利亚
2017/01/18 全球购物
印度尼西亚最好的小工具在线商店:Erafone.com
2019/03/26 全球购物
英国家居用品和床上用品零售商:P&B Home
2020/01/16 全球购物
解释一下钝化(Swap out)
2016/12/26 面试题
Java Servlet的主要功能和作用是什么
2014/02/14 面试题
绘画设计学生的个人自我评价
2013/09/20 职场文书
网络公司美工设计工作个人的自我评价
2013/11/03 职场文书
个人廉洁自律承诺书
2014/03/27 职场文书
学习方法演讲稿
2014/05/10 职场文书
三好学生评选事迹材料(2016精选版)
2016/02/25 职场文书
手把手教你怎么用Python实现zip文件密码的破解
2021/05/27 Python
SpringCloud超详细讲解Feign声明式服务调用
2022/06/21 Java/Android