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
PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法
Mar 10 PHP
PHP 作用域解析运算符(::)
Jul 27 PHP
php中使用parse_url()对网址进行解析的实现代码(parse_url详解)
Jan 03 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
Jun 03 PHP
smarty模板引擎中自定义函数的方法
Jan 22 PHP
php遍历删除整个目录及文件的方法
Mar 13 PHP
php生成图片缩略图的方法
Apr 07 PHP
教你在PHPStorm中配置Xdebug
Jul 27 PHP
PHP实现递归复制整个文件夹的类实例
Aug 03 PHP
PHP获取日期对应星期、一周日期、星期开始与结束日期的方法
Jun 22 PHP
PHP中abstract(抽象)、final(最终)和static(静态)原理与用法详解
Jun 05 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 开源AJAX框架14种
2009/08/24 PHP
PHP开发工具ZendStudio下Xdebug工具使用说明详解
2013/11/11 PHP
Laravel日志用法详解
2016/10/09 PHP
PHP实现RSA签名生成订单功能【支付宝示例】
2017/06/06 PHP
一个简单的js鼠标划过切换效果
2010/06/30 Javascript
javascript两种function的定义介绍及区别说明
2013/05/02 Javascript
刷新页面的几种方法小结(JS,ASP.NET)
2014/01/07 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
JS基于FileSystemObject创建一个指定路径的TXT文本文件
2015/08/05 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
2016/06/13 Javascript
纯JavaScript 实现flappy bird小游戏实例代码
2016/09/27 Javascript
webpack公共组件引用路径简化小技巧
2018/06/15 Javascript
基于React+Redux的SSR实现方法
2018/07/03 Javascript
Vue+Django项目部署详解
2019/05/30 Javascript
jQuery 判断元素是否存在然后按需加载内容的实现代码
2020/01/16 jQuery
基于ajax实现上传图片代码示例解析
2020/12/03 Javascript
在Python中操作列表之List.pop()方法的使用
2015/05/21 Python
python操作xlsx文件的包openpyxl实例
2018/05/03 Python
多个应用共存的Django配置方法
2018/05/30 Python
Python实现Singleton模式的方式详解
2019/08/08 Python
pytorch中的transforms模块实例详解
2019/12/31 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
Django 项目通过加载不同env文件来区分不同环境
2020/02/17 Python
Django框架配置mysql数据库实现过程
2020/04/22 Python
Python Tornado核心及相关原理详解
2020/06/24 Python
Selenium结合BeautifulSoup4编写简单的python爬虫
2020/11/06 Python
美国顶级户外凉鞋品牌:Chacos
2017/03/27 全球购物
美国购买韩国护肤和美容产品网站:Althea Korea
2020/11/16 全球购物
音乐学个人的自荐书范文
2013/11/26 职场文书
《两个铁球同时着地》教学反思
2014/02/13 职场文书
公开承诺书格式
2014/05/21 职场文书
2014年团员学习十八大思想汇报
2014/09/13 职场文书
党的群众路线教育实践活动个人整改落实情况汇报
2014/10/28 职场文书
十大最强飞行系宝可梦,BUG燕上榜,第二是飞行系王者
2022/03/18 日漫
SQL解决未能删除约束问题drop constraint
2022/05/30 SQL Server
Win11自动黑屏怎么办 Win11自动黑屏设置教程
2022/07/15 数码科技