简介:PHP设计模式之适配器模式
适配器模式就是将截然不同的函数接口封装成统一的API。其实就是定义一套规范,将同一类操作按同一套规范进行编程。
例如:
PHP的数据库操作有mysql、mysqli及pdo三种方式,可以用适配器模式统一成一致。类似的场景还有cache适配器,将memcache、redis、file等不同的缓存函数统一成一致。
实现原理:
首先我们定义一个规范。这个规范我们可以使用 interface 来实现
// 定义数据库规范接口
interface Database {
// 定义数据库连接接口
function connect($host,$user,$passwd,$dbname);
// 定义查询接口
function query($sql);
// 定义关闭接口
function close();
}
定义好接口后,我们在实际的操作类中去实现Database接口
// mysql操作数据库实际的类
class Mysql implements Database {
protected $connect;
// 实现Database接口中定义好的方法
public function connect($host, $user, $passwd, $name)
{
$connect = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname, $connect);
$this->connect = $connect;
}
// 查询数据
public function query($sql)
{
return mysql_query($sql, $this->connect);
}
// 关闭数据库
public function close()
{
mysql_close($this->connect);
}
}
上一章我们讲了注册树模式,我们可以将适配器与注册树模式结合。以上述mysql连接场景为例,实际工作中最终选择使用哪种方式取决与PHP安装环境。我们可以判断当前是否安装pdo等扩展来确定,确定好了之后就可以将最终对象注册到树上,其他地方直接使用即可。即使有扩展有变,我们也不需要去修改代码。
其他适配器模式的使用场景:
一般为了兼容历史代码在原有的基础类下进行扩展,通过使用(继承+实现) 和 组合继承 的方式来实现兼容性。接下来我们来看看这两个适配器方式的实现及不同点。
类适配器:使用(继承+实现)的方式
<?php
// 定义好的目标接口
interface Target{
function AdapteeRequest() : void;
function Request() : void;
}
//原接口类
class Adaptee {
function AdapteeRequest() : void{
}
}
// 通过继承原来的接口类+实现目标接口 = 适配器类
class Adapter extends Adaptee implements Target{
function Request() : void {
}
}
// 由于Adapter类继承了原来的Adaptee类,所以我们在调用Adapter类时就可以调用原有的方法和属性,
// 由此在不修改原类的前提下做到了兼容
$adapter = new Adapter();
$adapter->Request();
$adapter->AdapteeRequest();
对象适配器:使用的是组合继承方式
<?php
// 目标接口
interface Target{
function Request() : void;
}
//原接口类
class Adaptee {
function AdapteeRequest() : void{
}
}
//适配器类
class Adapter implements Target{
private $adaptee;
//实例化对象时把原来的对象存储在属性中
function __construct($adaptee){
$this->adaptee = $adaptee;
}
// 通过调用原对象实现的Request方法来兼容旧的逻辑
function Request() : void {
$this->adaptee->AdapteeRequest();
}
}
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
$adapter->Request();
通过以上代码可以看出:使用类适配器模式是通过继承+接口的方式实现了PHP的多继承,对象适配器则是通过将对象传参和继承的组合形式实现的。我个人比较喜欢类适配器,使用时不需要创建原来的类,更为方便
有遗漏或者不对的可以在我的公众号留言哦