zoukankan      html  css  js  c++  java
  • 反射API(二)

    <?php
    /**
     * 需求:
     * 创建一个类来动态调用Module对象,
     * 即该类可以自由加载第三方插件并集成进已有的系统,而不需要把第三方的代码硬编码进原有的代码。
     */
    class Person {
        public $name;
        function __construct($name)
        {
            $this->name = $name;
        }
    }
    
    interface Module
    {
        public function execute();
    }
    
    class PersonModule implements Module
    {
        public function setPerson(Person $person)
        {
            echo 'PersonModule::setPerson():'.$person->name.PHP_EOL;
        }
    
        public function execute()
        {
            echo __METHOD__.PHP_EOL;
        }
    }
    
    class FtpModule implements Module
    {
        public function setHost($host)
        {
            echo 'FtpModule::setHost():'.$host.PHP_EOL;
        }
    
        public function setUser($user)
        {
            echo 'FtpModule::setUser():'.$user.PHP_EOL;
        }
    
        public function execute()
        {
            echo __METHOD__.PHP_EOL;
        }
    }
    
    class ModuelRunner
    {
        // 定义配置 要加载的模型名和要调用的setXxx()函数
        private $configData = [
            'PersonModule' => ['person' => 'bob'],
            'FtpModule' => ['host' => 'example', 'user' => 'anon']
        ];
        // 保存实例化的模型对象
        private $modules = [];
    
        // 初始化 创建正确的Module对象
        public function init()
        {
            $interface = new ReflectionClass('Module');
            foreach ($this->configData as $moduleName => $params) {
                $module_class = new ReflectionClass($moduleName);
                // 确保模块类属于Module类型
                if (!$module_class->isSubclassOf($interface)) {
                    throw new Exception('unkonwn module type:'.$moduleName);
                }
                // 从指定的参数创建一个新的类实例
                $module = $module_class->newInstance();
                // 获得类中的所有方法
                foreach ($module_class->getMethods() as $method) {
                    $this->handleMethod($module, $method, $params);
                }
                // 保存模型对象
                $this->modules[$moduleName] = $module;
            }
        }
    
        // 检验并调用setXxx()方法
        public function handleMethod(Module $module,ReflectionMethod $method, $params)
        {
            // 获取方法名字
            $name = $method->getName();
            // 获取 ReflectionParmeter 对象组成的数组
            $args = $method->getParameters();
    
            // 规定所有的setter方法必须带有单个参数:字符串或者对象
            if (count($args)!=1 || substr($name, 0, 3) != 'set') {
                return false;
            }
    
            // 获取setXxx方法的参数值
            $property = strtolower(substr($name, 3));
            if (!isset($params[$property])) {
                return false;
            }
    
            // 判断参数是否是对象
            $arg_class = $args[0]->getClass();
            if (empty($arg_class)) {
                // 否 执行
                $method->invoke($module, $params[$property]);
            } else {
                //
                $method->invoke($module, $arg_class->newInstance($params[$property]));
            }
        }
    
        public function __get($name)
        {
            if ($name == 'modules') {
                return $this->modules;
            }
        }
    
    }
    
    echo '<pre>';
    $test = new ModuelRunner();
    $test->init();
    echo '<hr>调用execute()<br>';
    $module_obj = $test->modules;
    $module_obj['FtpModule']->execute();
    $module_obj['PersonModule']->execute();
  • 相关阅读:
    JS命名空间的使用
    PHPexcel的用法
    python爬取百度贴吧帖子
    python自动抢票
    int 与 String 与 char 之间的互相转换
    数据库备份和恢复
    Mysql 基础
    Mysql错误:Every derived table must have its own alias
    frameset框架集
    文件的上传(TCP)
  • 原文地址:https://www.cnblogs.com/cshaptx4869/p/10332285.html
Copyright © 2011-2022 走看看