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面向对象全攻略 (二) 实例化对象 使用对象成员
Sep 30 PHP
小谈php正则提取图片地址
Mar 27 PHP
codeigniter中测试通过的分页类示例
Apr 17 PHP
php中simplexml_load_file函数用法实例
Nov 12 PHP
Win7下手动安装apache2.2、php5.4笔记
Apr 03 PHP
PHP获取当前日期和时间及格式化方法参数
May 11 PHP
PHP7安装Redis扩展教程【Linux与Windows平台】
Sep 30 PHP
PHP中字符串长度的截取用法示例
Jan 12 PHP
PHP实现大数(浮点数)取余的方法
Feb 18 PHP
PHP实现简易计算器功能
Aug 28 PHP
实例说明js脚本语言和php脚本语言的区别
Apr 04 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+FLASH实现上传文件进度条相关文件 下载
2007/07/21 PHP
window+nginx+php环境配置 附配置搭配说明
2010/12/29 PHP
非常实用的php弹出错误警告函数扩展性强
2014/01/17 PHP
PHP链接MySQL的常用扩展函数
2014/10/23 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
JavaScript动态添加列的方法
2015/03/25 Javascript
Javascript监视变量变化的方法
2015/06/09 Javascript
如何利用AngularJS打造一款简单Web应用
2015/12/05 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
Nodejs进阶:核心模块net入门学习与实例讲解
2016/11/21 NodeJs
详解 vue.js用法和特性
2017/10/15 Javascript
JavaScript禁用右键单击优缺点分析
2019/01/20 Javascript
React中使用外部样式的3种方式(小结)
2019/05/28 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
2020/02/15 Javascript
vue抽出组件并传值实例
2020/07/31 Javascript
[03:23:49]2016.12.17日完美“圣”典全回顾
2016/12/19 DOTA
Python易忽视知识点小结
2015/05/25 Python
详解python中的线程
2018/02/10 Python
Python嵌套列表转一维的方法(压平嵌套列表)
2018/07/03 Python
python八皇后问题的解决方法
2018/09/27 Python
Python实现随机创建电话号码的方法示例
2018/12/07 Python
python判断计算机是否有网络连接的实例
2018/12/15 Python
Django 自动生成api接口文档教程
2019/11/19 Python
python手机号前7位归属地爬虫代码实例
2020/03/31 Python
keras 模型参数,模型保存,中间结果输出操作
2020/07/06 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
美国娱乐和流行文化商品店:FYE
2017/09/14 全球购物
伦敦高达60%折扣的钻石珠宝商:Purely Diamonds
2018/06/24 全球购物
吉列剃须刀美国官网:Gillette美国
2018/07/13 全球购物
私有程序集与共享程序集有什么区别
2013/04/05 面试题
MIS软件工程师的面试题
2016/04/22 面试题
客服主管岗位职责
2013/12/13 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
2014年党务公开工作总结
2014/12/09 职场文书
四年级作文之说明文作文
2019/10/14 职场文书