• 用反射加载第三方类用处在于:
  1. 使用XML或其他配文件配置要加载的类,从而和系统源代码分离
  2. 对加载的类进行类检查,是加载的类符合自己定义的结构

 

  1 <?php
  2     abstract class Module {    #核心Module类库
  3         function baseFunc() {
  4             echo "I am baseFunc";
  5         }
  6         
  7         abstract function execute();
  8     }
  9     
 10     class ModuleRunner {
 11         private $configData = array(    #模拟xml配置,动态配置需要加载的Module
 12             "PersonModule" => array("person" => "bob"),
 13             "FtpModule" => array("host" => "example.com", "user" => "anon")
 14         );
 15         
 16         private $modules = array();
 17         
 18         function init() {    #初始化ModuleRunner,加载配置中的Module
 19             $parent = new ReflectionClass("Module");
 20             foreach($this->configData as $moduleName => $params) {    #检查配置中的Module是否合法
 21                 $moduleClass = new ReflectionClass($moduleName);
 22                 if(! $moduleClass->isSubclassOf($parent)) {    #检查是否是Module的子类型
 23                     throw new Exception("unknown type : {$moduleName}");
 24                 }
 25                 $module = $moduleClass->newInstance();
 26                 foreach($moduleClass->getMethods() as $method) {    #检查配置中的函数的参数格式是否正确
 27                     $this->handleMothod($module, $method, $params);
 28                 }
 29                 array_push($this->modules, $module);    #加载Module
 30             }
 31         }
 32         
 33         private function handleMothod(Module $module, ReflectionMethod $method, $params) {    #检查Module中的方法参数是否和传入的$params名字相同,并且具有set方法
 34             $name = $method->getName();
 35             $args = $method->getParameters();
 36         
 37             if(count($args) != 1 || substr($name, 0, 3) != "set") {    #如果没有配置中的类的方法的参数个数不为1,或者方法名前3个字母不为set,返回false
 38                 return false;
 39             }
 40             
 41             $property = strtolower(substr($name, 3));
 42             if(!isset($params[$property])) {    #如果方法名后三个字母与配置中的参数名不同,返回false
 43                 return false;
 44             }
 45             
 46             $argClass = $args[0]->getClass();    #获取参数的类型
 47             if(empty($argClass)) {
 48                 $method->invoke($module, $params[$property]);    #参数无类型限制则直接调用set方法
 49             } else {
 50                 $method->invoke($module, $argClass->newInstance($params[$property]));    #有类型限制则新建一个实例并调用set方法
 51             }
 52         }
 53         
 54         public function getModules() {
 55             return $this->modules;
 56         }
 57     }
 58     
 59     class Person {    #第三方类
 60         public $name;
 61         
 62         function __construct($name) {
 63             $this->name = $name;
 64         }
 65     }
 66     
 67     class FtpModule extends Module {    #用户自定义第三方Module
 68         private $host = "default host";
 69         private $user = "default user";
 70         
 71         function setHost($host) {
 72             $this->host = $host;
 73         }
 74         
 75         function setUser($user) {
 76             $this->user = $user;
 77         }
 78         
 79         function execute() {
 80             echo "{$this->user} user {$this->host}";
 81         }
 82     }
 83     
 84     class PersonModule extends Module {    #用户自定义第三方Module
 85         private $person;
 86     
 87         function setPerson(Person $person) {
 88             $this->person = $person;
 89         }
 90         
 91         function execute() {
 92             if(isset($person)) {
 93                 echo "I am {$this->person->name}";
 94             } else {
 95                 echo "I am no user";
 96             }
 97         }
 98     }
 99     
100     $modRunner = new ModuleRunner();
101     $modRunner->init();
102     var_dump($modRunner);
103 ?>

输出

object(ModuleRunner)#1 (2) { ["configData":"ModuleRunner":private]=> array(2) { ["PersonModule"]=> array(1) { ["person"]=> string(3) "bob" } ["FtpModule"]=> array(2) { ["host"]=> string(11) "example.com" ["user"]=> string(4) "anon" } } ["modules":"ModuleRunner":private]=> array(2) { [0]=> object(PersonModule)#4 (1) { ["person":"PersonModule":private]=> object(Person)#10 (1) { ["name"]=> string(3) "bob" } } [1]=> object(FtpModule)#3 (2) { ["host":"FtpModule":private]=> string(11) "example.com" ["user":"FtpModule":private]=> string(4) "anon" } } }

posted on 2012-06-02 02:40  ZimZz  阅读(3122)  评论(0编辑  收藏  举报