这个话题源自最近工做中一个新项目的需求,该项目须要和数量不定的第三方平台进行对接,而这里提到的第三方平台会随着项目进度逐渐增长php
站在程序构架的角度,对于这种类型需求若是能够符合“对增长开放,对修改封闭”的设计标准,对于往后的运行和维护无疑都是一件好事。安全
固然,第一步咱们首先须要对第三方平台的对接接口和操做过程进行分析,并分解出统一调用时必要的接口。在php中咱们便可以使用类的继承,也能够进行独立的interface设计,这里仅做示例:编码
[php] view plaincopyspa
// 用做实现统一接口的父类,因此插件都须要继承自该类 .net
// 在调用时可用is_a,is_subclass_of,reflaction等进行检测 插件
class Plugin{ 设计
protected function init(){ orm
} 对象
protected function run(){ blog
}
}
// 示例用的自建插件
class TestPlugin1 extends Plugin{
}
class TestPlugin2 extends Plugin{
}
当咱们完成整个单个插件的接口设计后,下一步就须要一个对插件进行统一调用管理模块
先来考虑一下实现管理模块所面临的3个基本需求:如何检测到插件、如何验证插件有效性、如何加载插件、如何调用插件中的功能
一、如何检测到插件
一般状况下,在咱们导入一个新的class时,咱们就能够经过其类名对其进行实例化后的使用。可是在插件式的系统构架中,管理类所须要面对的是设计编码时各类未知的插件类名称,惟一的共同点只是这些类拥有共同的调用接口。因而,管理类如何检测插件就是咱们须要面对的第一个问题。
其实,虽然咱们在编码时并不知道插件的类名,但从根本上来讲在php运行过程当中,php解释器是必须实际知道每一个插件的类名才能对其进行实例化和调用的。这就意味着,咱们必须经过某种手段将须要调用的插件类引入,并得到其实际类名称。在这个配置过程当中,我我的将其分为动态配置和静态配置2大类。
以静态配置为例,咱们能够直接将所需引入的插件名称和其文件路径写入配置文件:
[php] view plaincopy
// key为引入类的类名,value为该类所需include的文件路径
$plugin_list = array(
'TestPlugin1' => 'inc/a.plugin.php',
'TestPlugin2' => 'inc/a.plugin.php'
)
若是以为静态配置过于繁琐,也能够经过指定插件文件夹,自动载入插件,在此再也不赘述。
二、验证插件有效性 以及 加载插件
当咱们完成插件的检测后,就能够经过依次引入插件文件、实例化插件类来进行插件加载了。若是考虑到系统稳定性和安全性,也能够在加载前适当的加入插件有效性验证,示例代码以下:
[php] view plaincopy
foreach($plugin_list as $name => $path){
@include_once(PATH . $path);
// 确保类的引入无误
if(!class_exists($name)){
continue;
}
// 实例化插件
$plugin = new $name();
// 检测插件是否继承自指定接口类
// 也能够经过反射机制的has_Methods对指定接口进行验证
if(!is_a($plugin, 'Plugin'){
continue;
}
// 验证经过,存储实例化后的插件对象
$my_plugins[$name] = $plugin;
}
三、调用插件接口
在完成以上2步以后,调用插件接口已是易如反掌了:
[php] view plaincopy
foreach($my_plugins as $name=>$plugin){
$plugin->init();
$plugin->run();
}