反射API的一个简单实例

    假设我们创建一个类要动态调用Module对象,即该类可以自动加载第三方插件并集成到已有的系统,而不需要把第三方插件硬编码进原有的代码。

    要达到这个目的,可以在Module接口或抽象类中定义一个execute()方法,强制要求所有子类都要实现这个方法,可以允许用户在外部XML文件中列出所有的Module类,系统可以用XML提供的信息加载一定数目的Module对象,然后每个Module对象调用execute()。XML文件可以为每个Module实现属性和值,Module的创建者可以为每个属性名提供setter方法。

interface Module{
	function execute();
}

class FtpModule implements Module{
	function setHost($host){
		print "FtpModule::setHost(): $host<br>";
	}
	function setUser($user){
		print "FtpModule::setUser(): $user<br>";
	}
	function execute(){

	}
}

class PresonModule implements Module{
	function setPerson(Person $person){
		print "PresonModule::setPerson(): $person->name<br>";
	}
	function execute(){

	}
}

class ModuleRunner{
	private $configData = array(
		"PresonModule" => array('person'=>'bob'),
		"FtpModule" => array(
			'host' => 'example.com',
			'user' => 'anon',
		),
	);
	private $modules = array();

	function init(){
		$interface = new ReflectionClass('Module');
		foreach ($this->configData as $modulename => $params) {
			$medule_class = new ReflectionClass($modulename);
			if(!$medule_class->isSubclassOf($interface)){
				throw new Exception("unknown medule type: $medulename");
			}
			$medule = $medule_class->newInstance();
			foreach ($medule_class->getMethods() as $method) {
				$this->handleMethod($medule, $method, $params);
				array_push($this->modules, $method);
			}
		}
	}

	function handleMethod(Module $module, ReflectionMethod $method, $params){
		$name = $method->getName();
		$args = $method->getParameters();
		if(count($args) != 1 || substr($name, 0, 3)!="set"){
			return false;
		}
		$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]));
		}
	}
}
$test = new ModuleRunner();
$test->init();


猜你喜欢

转载自blog.csdn.net/liu2446426696/article/details/77160536