在阅读一个PHP程序的时候,发现有很多地方都有重复的代码:
/* {{{ getXiaoquBaseInfoByCityPinyin 获取小区基本信息 */
/**
* 获取小区基本信息
* @param string $city 城市domain
* @param string $pinyin 小区拼音
* @return array 小区信息数组
*/
public function getXiaoquBaseInfoByCityPinyin($city, $pinyin) {
try {
//xiaoqu_xiaoqu
$xiaoquModel = PlatformSingleton::getInstance('XiaoquXiaoquXiaoquModel');
$result = $xiaoquModel->getXiaoquInfoByCityPinyin($city, $pinyin);
$data = array(
'errorno' => ErrorConst::SUCCESS_CODE,
'errormsg' => ErrorConst::SUCCESS_MSG,
'data' => $result,
);
} catch (Exception $e) {
$data = array(
'errorno' => $e->getCode(),
'errormsg' => $e->getMessage(),
);
}
return $data;
} //}}}
/* getXiaoquStatInfoByXiaoquId 获取小区统计信息 {{{ */
/**
* 获取小区统计信息
* @param int $xiaoquId 小区id
* @param array $fields 要查询的列
* @return array
*/
public function getXiaoquStatInfoByXiaoquId($xiaoquId, $fields=array()) {
try {
$model = PlatformSingleton::getInstance('XiaoquStatXiaoquModel');
$xiaoquIds = array($xiaoquId);
$result = $model->getXiaoquStatInfoByXiaoquId($xiaoquIds, $fields);
$data = array(
'errorno' => ErrorConst::SUCCESS_CODE,
'errormsg' => ErrorConst::SUCCESS_MSG,
'data' => $result[0],
);
} catch (Exception $e) {
$data = array(
'errorno' => $e->getCode(),
'errormsg' => $e->getMessage(),
);
}
return $data;
} //}}}
一个类有740多行,大量相同的代码,如上面绿色部分都是重复的,感觉应该有办法改进。于是想了解PHP中是否有匿名类或者模板方法的做法。
在java中,一般可以这样来做:
public class A{
public static void execute(B b){
try{
var xxx = b.dosth();
fmt xxxx;
return xxx;
}catch(Exception e){
deal exception;
}
}
}
public interface B {
public abstract void dosth();
}
public class Test{
public static void main(String[] argv){
var xxx = A.execute(new B(){
public void dosth(){ dosth reallly;}
}
}
}
上面代码,先定义了一个A的模板方法类,其execute方法中接受一个接口B的入参b,并在execute方法中调用了b的dosth方法来完成,execute方法本身提供了变量初始化xxx,和异常包装。在调用的时候(粉色代码)实际上使用了匿名内部类,动态的初始化了一个B的对象,并直在代码片段的时候完成了实现。
这个方法需要注意:
1、如果new B(){public void dosth()}里面要用到局部变量,需要将变量定义为final,不可修改,避免出现上下文依赖关系;
2、B的接口dosth的返回值将直接在excute方法中使用,而方法Test中处理的函数可能是个性的,有可能出现类型转换,通常做法是直接使用Object作为返回类型;
对PHP不熟悉,于是参照这个调查了一下php的匿名函数,发现匿名函数是在5.3以后才支持的,于是可以简单得到这样的代码:
[code]
<?php
class A
{
public static function warpException($fun)
{
$astr = "string from warp Exception";
return $fun($astr);
}
}
class B
{
public function methodB($bstr)
{
$fun = function($mystr) use($bstr)
{
return $mystr.':'.$bstr;
};
$bstr="str modified";
$result = A::warpException($fun);
return $result;
}
}
class C
{
public function methodC($bstr)
{
$bstr="str modified";
$result = A::warpException(function($mystr) use($bstr)
{
return $mystr.':'.$bstr;
});
return $result;
}
}
$b = new B();
$re = $b->methodB("this is just a test");
echo $re,"\n";
echo $b->methodB("new Test"),"\n";
$c = new C();
echo $c->methodC("this is just a test"),"\n";
[/code]
其中使用了PHP的匿名函数,如绿色部分。需要注意:
1、PHP5.3以后才支持匿名函数,尚未大规模推广,使用要注意坑;
2、实际上匿名函数就是闭包;
3、在使用的时候要注意use局部变量,避免出现变量变化以后内容不同;
4、在use的时候实际上已经对变量进行了一次值拷贝,后面如果有任何对变量的修改并不会发生变化。上述代码运行结果:
➜ php> php AnyClassTest.class.php
string from warp Exception:this is just a test
string from warp Exception:new Test
string from warp Exception:str modified
此外,如果你使用的代码没有升级到5.3以后,可以使用__call进行封装,如: