php解耦的三种境界
我们有三个类,Db,FileSystem,Session;实际业务需求要组合操作这三个类.
一.常规做法
class Db { public function read($id) { } } class FileSystem { public function writeFile($file) { } } class Session { public function setSession($sessionName) { } } // 实际逻辑 class Logic { protected $db; protected $file; protected $session; public function __construct() { $this->db = new Db(); $this->file = new FileSystem(); $this->session = new Session(); } public function handle($id) { if ($name = $this->db->read($id)) { $this->file->writeFile(md5($name) . '.txt'); $this->session->setSession($id); } } } $id = 11; $client = new Logic(); $client->handle($id);
缺点:
Logic内部高度耦合了,Db,FileSystem,Session
如果这三个类的初始化条件变化,则需要修改Logic的构造方法.
二.参数依赖(类型提示,将新建关联类的放入调用处)
修改Logic代码如下:
class Logic { protected $db; protected $file; protected $session; public function __construct(Db $db, FileSystem $file, Session $session) { $this->db = $db; $this->file = $file; $this->session = $session; } public function handle($id) { if ($name = $this->db->read($id)) { $this->file->writeFile(md5($name) . '.txt'); $this->session->setSession($id); } } } $id = 11; $db = new Db(); $file = new FileSystem(); $session = new Session(); $client = new Logic($db, $file, $session); $client->handle($id);
优点:
实现了解耦
缺点:
业务变动,如果要更改Db类到MySql类或初始化条件变动,代码依然要改动.
ps:大部分的设计模式使用了该解耦方法.
三.容器
1.希望DB类,Session类,FileSystem类“拿来即用”,不用每次繁琐的初始化,比如写$db=new DB(arg1,arg2);这类语句。
2.希望DB等类型的对象是“全局”,在整个程序运行期间,随时可以调用。
3.调用DB等类型的程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。
能够实现以上目标的就是IOC容器,可以把IOC容器简单的看成一个全局变量,并用关联数组把字符串和构造函数做绑定
// 容器 class Container { public $binds = array(); public function bind($abstract, $concreate) { $this->binds[$abstract] = $concreate; } public function make($abstract, $params = []) { return call_user_func_array($this->binds[$abstract], $params); } } // 绑定或注册 $container = new Container(); $container->bind('db', function () { return new Db(); }); $container->bind('file', function () { return new FileSystem(); }); $container->bind('session', function () { return new Session(); }); // 实际逻辑,容器依赖 class Logic { protected $db; protected $file; protected $session; public function __construct(Container $container) { $this->db = $container->make('db'); $this->file = $container->make('file'); $this->session = $container->make('session'); } public function handle($id) { if ($name = $this->db->read($id)) { $this->file->writeFile(md5($name) . '.txt'); $this->session->setSession($id); } } } $id = 11; $logic = new Logic($container); $logic->handle($id);
本文参考自:https://www.cnblogs.com/sweng/p/6430374.html