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();
  • 相关阅读:
    C# 操作配置文件
    C# Excel操作类
    没有找到 mspdb100.dll 的解决办法
    工厂方法模式
    .Net互操作2
    The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决
    手机抓包xcode自带命令行工具配合wireshark实现
    expecting SSH2_MSG_KEX_ECDH_REPLY ssh_dispatch_run_fatal问题解决
    使用ssh-keygen设置ssh无密码登录
    远程复制文件到服务器
  • 原文地址:https://www.cnblogs.com/cshaptx4869/p/10332285.html
Copyright © 2011-2022 走看看