這個話題源自最近工做中一個新項目的需求,該項目須要和數量不定的第三方平臺進行對接,而這裏提到的第三方平臺會隨着項目進度逐漸增長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();
}