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实现框架(二)
Oct 09 PHP
ajax+php打造进度条代码[readyState各状态说明]
Apr 12 PHP
ThinkPHP实现支付宝接口功能实例
Dec 02 PHP
php实现scws中文分词搜索的方法
Dec 25 PHP
java微信开发之上传下载多媒体文件
Jun 24 PHP
微信支付开发订单查询实例
Jul 12 PHP
PHP生成图像验证码的方法小结(2种方法)
Jul 18 PHP
PHP在线打包下载功能示例
Oct 15 PHP
thinkPHP5.0框架模块设计详解
Mar 18 PHP
swoole_process实现进程池的方法示例
Oct 29 PHP
记Laravel调用Gin接口调用formData上传文件的实现方法
Dec 12 PHP
TP框架实现上传一张图片和批量上传图片的方法分析
Apr 23 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事务处理实例详解
2014/07/11 PHP
浅谈php优化需要注意的地方
2014/11/27 PHP
PHP中把对象数组转换成普通数组的方法
2015/07/10 PHP
PHP unlink与rmdir删除目录及目录下所有文件实例代码
2018/02/07 PHP
PHP大文件分割分片上传实现代码
2020/12/09 PHP
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
javascript unicode与GBK2312(中文)编码转换方法
2013/11/14 Javascript
Javascript使用post方法提交数据实例
2015/08/03 Javascript
仅一个form表单 js实现注册信息依次填写提交功能
2016/06/12 Javascript
JavaScript 中 apply 、call 的详解
2017/03/21 Javascript
BootStrap+Mybatis框架下实现表单提交数据重复验证
2017/03/23 Javascript
js实现关闭网页出现是否离开提示
2017/12/07 Javascript
详解vue-cli3使用
2018/08/14 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
2018/11/30 Javascript
node.js 基于cheerio的爬虫工具的实现(需要登录权限的爬虫工具)
2019/04/10 Javascript
使用JavaScript通过前端发送电子邮件
2020/05/22 Javascript
详解React中共享组件逻辑的三种方式
2021/02/02 Javascript
python迭代器的使用方法实例
2013/11/21 Python
详细讲解Python中的文件I/O操作
2015/05/24 Python
Python切片索引用法示例
2018/05/15 Python
对python requests的content和text方法的区别详解
2018/10/11 Python
解决安装pycharm后不能执行python脚本的问题
2019/01/19 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
简单瞅瞅Python vars()内置函数的实现
2019/09/27 Python
pytorch 自定义卷积核进行卷积操作方式
2019/12/30 Python
伦敦所有西区剧院演出官方票务代理:Theatre Tickets Direct
2017/05/26 全球购物
大学毕业通用个人的求职信
2013/12/08 职场文书
《悯农》教学反思
2014/04/28 职场文书
民主评议党员自我评议范文2014
2014/09/26 职场文书
计生办班子群众路线教育实践活动个人对照检查材料思想汇报
2014/10/04 职场文书
销售业务员岗位职责
2015/02/13 职场文书
创业计划书之养殖业
2019/10/11 职场文书
MongoDB balancer的使用详解
2021/04/30 MongoDB
Ajax异步刷新功能及简单案例
2021/11/20 Javascript
Python实现文字pdf转换图片pdf效果
2022/04/03 Python
Mysql查询时间区间日期列表,不会由于数据表数据影响
2022/04/19 MySQL