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面向对象全攻略 (十六) 对象的串行化
Sep 30 PHP
php foreach 使用&(与运算符)引用赋值要注意的问题
Feb 16 PHP
php中突破基于HTTP_REFERER的防盗链措施(stream_context_create)
Mar 29 PHP
php长字符串定义方法
Jul 12 PHP
Zend studio文件注释模板设置方法
Sep 29 PHP
php实现的css文件背景图片下载器代码
Nov 11 PHP
PHP易混淆函数的区别及用法汇总
Nov 22 PHP
PHP中的替代语法介绍
Jan 09 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
php无限级分类实现方法分析
Oct 19 PHP
详解php中生成标准uuid(guid)的方法
Apr 28 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 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生成固定长度纯数字编码的方法
2015/07/09 PHP
深入浅析PHP7.0新特征(五大新特征)
2015/10/29 PHP
PHP自定义递归函数实现数组转JSON功能【支持GBK编码】
2018/07/17 PHP
jQuery 通过事件委派一次绑定多种事件,以减少事件冗余
2010/06/30 Javascript
Javascript变量的作用域和作用域链详解
2015/04/02 Javascript
JS实现弹出浮动窗口(支持鼠标拖动和关闭)实例详解
2015/08/06 Javascript
jquery 表单验证之通过 class验证表单不为空
2015/11/02 Javascript
JS调用打印机功能简单示例
2016/11/28 Javascript
纯js实现悬浮按钮组件
2016/12/17 Javascript
在 Node.js 中使用 async 函数的方法
2017/11/17 Javascript
JS常见DOM节点操作示例【创建 ,插入,删除,复制,查找】
2018/05/14 Javascript
在vue中使用vue-echarts-v3的实例代码
2018/09/13 Javascript
JavaScript根据json生成html表格的示例代码
2018/10/24 Javascript
el-select数据过多懒加载的解决(loadmore)
2019/05/29 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
2019/08/26 Javascript
jquery+ajax实现异步上传文件显示进度条
2020/08/17 jQuery
[02:09]抵达西雅图!中国军团加油!
2014/07/07 DOTA
[56:46]Liquid vs IG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
[34:39]Secret vs VG 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
python爬虫面试宝典(常见问题)
2018/03/02 Python
python3实现随机数
2018/06/25 Python
django的ORM操作 增加和查询
2019/07/26 Python
Python中PyQt5/PySide2的按钮控件使用实例
2019/08/17 Python
opencv 阈值分割的具体使用
2020/07/08 Python
BOSE德国官网:尽探索之力,享音乐之极
2016/12/11 全球购物
Linux如何压缩可执行文件
2014/03/27 面试题
幼儿园教师备课制度
2014/01/12 职场文书
授权委托书样本
2014/04/03 职场文书
植树造林的宣传标语
2014/06/23 职场文书
教代会闭幕词
2015/01/28 职场文书
2015年老干部工作总结
2015/04/23 职场文书
2015年党务公开工作总结
2015/05/19 职场文书
初二英语教学反思
2016/02/15 职场文书
《七月的天山》教学反思
2016/02/19 职场文书
JavaScript 防篡改对象的用法示例
2021/04/24 Javascript
Python基本数据类型之字符串str
2021/07/21 Python