一、什么是适配器模式(Adapter Pattern)?
适配器模式,就是将不同的api接口,统一成一致的;实际应用举例,数据库操作有mysql、mysqli、pdo三种,但是它们的连接和操作方法是不一样的,我们可以用适配器将它们的操作接口封装成一致的。
类似场景还有cache适配器,将memcache、redis、file、apc等不同缓存函数适配一致;
适配器UML图
二、实现适配器
首先来了解三个类 的角色
1、Target适配目标 : 该角色定义把其他类转换为何种接口,也就是我们的期望接口。(可以是具体或抽象类,也可以是接口)
2、Adaptee被适配者 :就是需要被适配的接口。
3、Adapter适配器:其他的两个角色都是已经存在的角色,而适配器角色是需要新建立的,它用来对Adaptee与Target接口进行适配。
<?php
//用户所期待的接口 目标接口
Interface Target{
public function connect($host, $user, $passwd, $dbname);
public function query($sql);
public function close();
}
// MySQL 被适配的类,此类继承了Target
class MySQLAdaptee implements Target
{
protected $conn; //用于存放数据库连接句柄
//实现连接方法
public function connect($host, $user, $passwd, $dbname)
{
// mysql 连接数据库代码块
}
//查询方法
public function query($sql)
{
// mysql 查询代码块
}
//关闭方法
public function close()
{
// mysql 关闭代码块
}
}
// MySQLi 需要被适配的类,未继承Target类 (此类可继承Target,不过继承后,里面的方法需要和Target的方法一致)
class MySQLiAdaptee
{
protected $conn;
public function mysqliConnect($host, $user, $passwd, $dbname)
{
// mysqli 连接数据库代码块
}
public function mysqliQuery($sql)
{
// mysqli查询数据库代码块
}
public function mysqliClose()
{
// mysqli 关闭数据库代码块
}
}
// 适配器类Adapter ,此类为mysqli的适配器
class MysqliAdapter implements Target{
private $adaptee;
function __construct($adaptee) {
$this->adaptee = $adaptee;
}
//这里把异类的方法转换成了 接口标准方法,下同
public function connect(){
$this->adaptee->mysqliConnect();
};
public function query(){
$this->adaptee->mysqliQuery();
};
public function close(){
$this->adaptee->mysqliClose();
};
}
// 用户调用
$db = new MySQLAdaptee(); // 使用mysql方式
$db = new MysqliAdapter(new MySQLiAdaptee()); // 使用mysqli,以下调用方法与mysql是一致的
$db->connect('127.0.0.1','root','123','myDB');
$db->query('select * from test');
$db->close();
三、总结
这个适配器模式,看了网上很多种资料,有些资料感觉是个误区,比如以下这种
interface IDatabase
{
public function connect($host, $username, $password, $dbname);
public function query($sql);
public function close();
}
class Mysql implements IDatabase
{
protected $connect; // 连接资源
public function connect($host, $username, $password, $dbname)
{
// 连接
}
public function query($sql)
{
// 查询
}
public function close()
{
// 关闭
}
}
class Mysql_i implements IDatabase
{
protected $connect; // 连接资源
public function connect($host, $username, $password, $dbname)
{
// 连接
}
public function query($sql)
{
// 查询
}
public function close()
{
// 关闭
}
}
$client = new Mysql('127.0.0.1','root','123','mydb'); // 不同数据库操作切换
$client = new Mysql_i('127.0.0.1','root','123','mydb'); // 不同数据库操作切换
$client->connect($host, $username, $password, $database);
$client->query("select * from db");
$client->close();
咋一看好像没什么问题,实现了不同数据库类型,一致操作的方法,但是没有点到适配器的重点;
这里面的适配器类就是它本身,且两个类里面的方法名都是一致的,感觉并无意义;
个人理解:应该是不同类的不同方法名,通过适配器使方法变成一致;比如mysql类的connect方法,与mysqli类的mysqliconnect方法,通过适配器,使这两个方法在调用上保持一致;
大家有什么想法可在底下留言一起探讨,如果觉得此篇文章对您有用,请帮忙点个赞,谢谢!^_^