




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于反射的插件架构实际上并没有被归类为一种模式,因为它实际上不是一个模板,而是一系列组合在一起形成程序架构的概念。 接口要求所有的实现类声明定义在接口中的所有方法。对于严格的系统来说,这是理想的.但是在规模更大更复杂的系统中,两个交互的项本身也是交杂程序的情况下,这可能会导致程序发生故障, 反射APl的插件方法是基于在运行时决定程序逻辑的功能来实现的.也就是说.它允许创建可选的接口方法 .并且在首次使用时检测到这些接口方法。只有在插件中存在这些方法的情况下.它门才会被用到。否则,它们就会被忽略。这有助于避免实现复杂的接口,从而支持史灵活的定制情况 Interface Iplugin Function getMenuItems(); Function getArticles(); Function getSideBars();Class SomePlugin implements Iplugin Public function getMenuItems() Return null;Public function getArticles()Return nullPublic function getSideBars()Return array(SideBarItem); 这种情况井不太合理,因为为了满足接口的要求,为大量方祛添加了不会用到的函数体。如果在APl中有数百个方法,这肯定是行不通的。 现在你也许想到你可以将每个方法拆分到它自己的接口中,但同样的问题也会发生。会出现一个实现了数百个接口的类,还会出现数百个接口的声明,这同样不太现实。 一些语言是事件驱动的.它们提供了委托方法,可以从宿主应用程序中接收到事件,但PHP没有内置的委托支待。所以,很多框架都定义了复杂的一套钩子函数,它们要求插件在某些形式的初始化过程中注册插件自身的能力。这种初始化过程和注册API吏得创建插件的工作更加困难,所以开发的插件数量很少。 反射.4P1哭供了一种解决方案。在这一方案中:可以get_declared_classes()函数获取所有当前加载的类,并检测哪个类实现了一个单方法的IPlugin“标记”接口这个接口与整个API相比要简单得多,但是它会包含一个getName()函数,所有插件都必须包含这个函数。 作为示例,我们将演示如何以基于插件的系统的方式创建一个非常基本的Web页面。页面包含菜单、侧边栏和文章。通过反射,应用程序将检测到每个插件支持的特性,并且只有在这个特性存在时才会执行相应的方法。这个例子非常简单,不是作为一个整体的应用程序来设计的.但它演示了使用反射来加载插件的方法。首先,我们需要创建一个所有插件都必须遵循的接口,名为IpluginInterface Iplugin Public static function getName(); 这个接口很简单。它仅仅定义了一个要求所有插件都必须实现的方法口 下-步,我们需要创建一个子程序去检测所有当前已包含的插件。要实现这一点,只需要使用get_declared_classes()函数和ReflectiononClass类,如代码清单所示。使用反射查找插件Function findPlugins() $plugins =array(); Foreach(get_declared_classes() as $class) $reflectionClass = new ReflectionClass($class); If($reflectionClass-implementsInterface(IPlugin) $plugins=$reflectionclass; Return $plugins; 代码使用了ReflectionClass类的implementsInterface()方法来检测某个类是否实现了IPlugin接口。这个方法的作用正如其名称所表示的那样,它检查类是否实现了某个接口。与instanceof操作符不同的是,这个方法并不需要操作类的实例,因此更高效: 应该注意到,这段代码保存了ReflectionClass的实例.而不是类的实例或者作为字符串的名称。这是因为创建反射类会有一些开销,在稍后调用捅件的方法之前要检查插件是否具有特定的属性。所以需要现在就将它保存起来,这样就不用执行两次实例化工作了。 找到插件后,还需要创建一种机制去检测插件提供的应用程序功能的子集。例如,包含菜单项的插件将会定义一个为法,用来向菜单添加菜单项,而侧边栏插件没有这个方法。为了确定某类是否实现了某个方法.可以使用ReflectionClass类的hasMethod ()方法口Function computeMenu() $menu = array(); Foreach(findPlugins() as $plugin) If($plugin-hasMethod(getMenuItems) $reflectionMethod = $plugin-getMethod(getMenuItems); If($reflectionMethod-isStatic() $items = $reflectionMethod-invoke(null);else /如果这个方法不是静态的,我们需要一个实例 $pluginInstance = $plugin-newInstance();$items = $reflectionMethod-invoke($pluginInstace);$menu = array_merge($menu,$item);Return $menu; computeMenu()函数的作用是返回一个菜单项的数组。假设现在有一个menuItem类;这个类的实例将被作为数组项保存在$menu中。 下一步,使用findPlugins()函数找到所有的插件。因为之前己经将所有插件的ReflectionClass实例保存在一个数组中,所以就不再需要重新创建这些实例了,只需要迭代访问这些插件以获得反射信息。 现在,应用程序需要检测是否每个插件都有菜单项。根据设计,对于插件来说,创建菜单项是可选的。通过使用ReflectionClass实例的hasMethnd I方法,可以检测插件是否包包含这一功能。找到这个方法后.还需要获得这个方法的反射器。 ReflectionClass实例的ge tMe t hod ()方法返回另外一个反射器类,即ReflectionMethod与RflectionClass类相似,ReflectionMethod类提供了访问元数据的能力,但这个元数据是与方法相关的而不是与类相关的。通过获得ReflectionMethod实例,可以查询这个方法以确定它的元数据。 获得ReflectionMethod实例后,需要检测是否能够静态地调用APf方法,如果方法是静态的,只需要调用inuoke()函数.而不需要去创建插件的实例了。ReflectionMethod类的invoke()方法拥有以下签名。Public mixed invoke(stdclass object,mixed args=null) 要调用一个静态方法,必须为invoke()方法的第一个参数传入一个隐式的null值。 另一方面,如果方法不是静态的,需要获得插件的一个实例来调用这个方法。要从ReflectionClass对象获得类的一个实例,需要调用它的newInstance()方法。然后.假设构造这个实例的过程正常,就可以调用ReflectionMethod类的invoke()方法.将newInstance()返回的实例传入即可。 然后,把插件返回的所有菜单项合并到$menu数组中。在处理完所有插件之后,将会返回整个$menu数组。 使用同样的技术,你还可以为文章和侧边栏创建一样的特性。Function computeArticles() $articles = array(); Foreach(findPlugins() as $plugin) If($plugin-hasMethod(getArticles) $reflectionMethod=$plugin-getMethod(getArticles); If($reflectionMethod-isStatic() $items = $reflectionMethod-invoke(null);else $pluginInstance = $plugin-newInstance(); $items = $reflectionMethod-invoke($pluginInstance); $articles = array_merge($articles,$items); Return $articles;Function computeSidebars() $sidebars = array(); Foreach(findPlugins() as $plugin) If($plugin-hasMethod(getSidebars) $reflectionMethod=$plugin-getMethod(getSidebars); If($reflectionMethod-isStatic() $items = $reflectionMethod-invoke(null);else $pluginInstance = $plugin-newInstance(); $items = $reflectionMethod-invoke($pluginInstance); $articles = array_merge($sidebars,$items); Return $ sidebars;下一步,需要创建一个实现了IPlugin的类如代码所示。这个插件类实现了一个菜单项和一篇文章,但是没有实现侧边栏。MyCoolPlugin, link=/MyCoolPlugin);Public static function getArticles()Return array(array( path=/MyCoolPlugin, title=This is a really cool article, text=This article is cool because);?这个插件在提供了一些功能。下面代码是使用这个插件的一个非常基本的例子。使用插件Require_once(/path/to/plugin.php);$menu = co
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 购物中心公共区域保洁服务合同
- 职业教育校企合作信息管理平台
- 书香满屋生活更有味
- 烤面包机维修预案思路
- 2025中国工商银行山西省分行社会招聘120人笔试含答案
- 卡通动漫绘画风格规定
- 2025浙江宁波江北区劳动和社会保障事务代理服务有限公司招聘编外工作人员笔试历年参考题库附带答案详解
- 企业财务造假审计
- 2025锡林郭勒西乌珠穆沁旗招聘基层医疗卫生机构专业技术人员笔试模拟试题及答案解析
- 企业完善员工工作环境
- 14J936变形缝建筑构造
- 人教版九年级英语全一册 Unit 13 《We are trying to save the earth!》教学设计
- 全套电子课件:极限配合与技术测量(第五版)
- 结构力学课件
- 人民检察院刑事诉讼法律文书格式样本2022
- (高清版)DZT 0216-2020 煤层气储量估算规范
- 人教版四年级上册语文第一单元测试题(含答案)
- 储能电站项目建设流程详解
- 供应商尽职调查模板
- 饮用水配送方案
- 妊娠滋养细胞肿瘤护理查房课件
评论
0/150
提交评论