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 相关文章推荐
php addslashes 函数详细分析说明
Jun 23 PHP
fleaphp rolesNameField bug解决方法
Apr 23 PHP
解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)
Jun 18 PHP
PHP无限分类(树形类)
Sep 28 PHP
PHP实现将浏览历史页面网址保存到cookie的方法
Jan 26 PHP
功能强大的PHP图片处理类(水印、透明度、旋转)
Oct 21 PHP
thinkphp多表查询两表有重复相同字段的完美解决方法
Sep 22 PHP
Linux服务器下PHPMailer发送邮件失败的问题解决
Mar 04 PHP
php JWT在web端中的使用方法教程
Sep 06 PHP
php基于协程实现异步的方法分析
Jul 17 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
Oct 15 PHP
PHP手机号码及邮箱正则表达式实例解析
Jul 11 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
PHP iconv 解决utf-8和gb2312编码转换问题
2010/04/12 PHP
PHP用SAX解析XML的实现代码与问题分析
2011/08/22 PHP
PHP中图片等比缩放的实例
2013/03/24 PHP
PHP中实现生成静态文件的方法缓解服务器压力
2014/01/07 PHP
使用ThinkPHP+Uploadify实现图片上传功能
2014/06/26 PHP
php实现扫描二维码根据浏览器类型访问不同下载地址
2014/10/15 PHP
php中动态变量用法实例
2015/06/10 PHP
php的闭包(Closure)匿名函数初探
2016/02/14 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
2016/10/29 PHP
php实现网页端验证码功能
2017/07/11 PHP
php处理抢购类功能的高并发请求
2018/02/08 PHP
JavaScript代码复用模式实例分析
2012/12/02 Javascript
asm.js使用示例代码
2013/11/28 Javascript
分享纯手写漂亮的表单验证
2015/11/19 Javascript
jQuery动画效果相关方法实例分析
2015/12/31 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
JavaScript模块模式实例详解
2017/10/25 Javascript
vue组件间通信六种方式(总结篇)
2019/05/15 Javascript
关于NodeJS中的循环引用详解
2019/07/23 NodeJs
JavaScript字符串处理常见操作方法小结
2019/11/15 Javascript
vue制作toast组件npm包示例代码
2020/10/29 Javascript
Python中的Descriptor描述符学习教程
2016/06/02 Python
Python对象类型及其运算方法(详解)
2017/07/05 Python
Python使用progressbar模块实现的显示进度条功能
2018/05/31 Python
Python实现正则表达式匹配任意的邮箱方法
2018/12/20 Python
Python 占位符的使用方法详解
2019/07/10 Python
python操作toml文件的示例代码
2020/11/27 Python
英国排名第一的在线宠物用品商店:Monster Pet Supplies
2018/05/20 全球购物
Antonioli美国在线商店:时尚前卫奢华
2019/07/29 全球购物
英文简历中的自我评价
2013/10/06 职场文书
电气工程及自动化专业自荐书范文
2013/12/18 职场文书
关于建议书的格式范文
2014/05/20 职场文书
2014年行政后勤工作总结
2014/12/06 职场文书
幼儿园大班教师个人工作总结
2015/02/05 职场文书
2015毕业寄语大全
2015/02/26 职场文书
郭明义观后感
2015/06/08 职场文书