php重构优化一例——模板方法模式应用
最近优化php项目,记录下经验,直接上干活。。。
php在公司项目中主要用于页面展现,前端有个view,view向后端的service请求数据,数据的传输格式是json。下面看优化前的service的代码:
[php]
<?php
require_once('../../../global.php');
require_once(INCLUDE_PATH . '/discache/CacherManager.php');
require_once(INCLUDE_PATH.'/oracle_oci.php');
require_once(INCLUDE_PATH.'/caihui/cwsd.php');
header('Content-type: text/plain; charset=utf-8');
$max_age = isset($_GET['max-age']) ? $_GET['max-age']*1 : 15*60;
if($max_age < 30) {
$max_age = 30;
}
header('Cache-Control: max-age='.$max_age);
// 通过将url进行hash作为缓冲key
$url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$url_hash = md5($url);
//echo "/finance/hs/marketdata/segment/${url_hash}.json";
if (!CacherManager::cachePageStart(CACHER_MONGO, "/finance/hs/marketdata/segment/${url_hash}.json", 60*60)) {
// 查询条件
$page = isset($_GET['page']) ? $_GET['page']*1 : 0;
$count = isset($_GET['count']) ? $_GET['count']*1 : 30;
$type = isset($_GET['type']) ? $_GET['type'] : 'query';
$sort = isset($_GET['sort']) ? $_GET['sort'] : 'symbol';
$order = isset($_GET['order']) ? $_GET['order'] : 'desc';
$callback = isset($_GET['callback']) ? $_GET['callback'] : null;
$fieldsstring = isset($_GET['fields']) ? $_GET['fields'] : null;
$querystring = isset($_GET['query']) ? $_GET['query'] : null;
$symbol=isset($_GET['symbol'])?$_GET['symbol']:'';
$date=isset($_GET['date'])?$_GET['date']:'';
if ($type == 'query') {
$queryObj = preg_split('/:|;/', $querystring, -1);
for($i=0; $i<count($queryObj); $i=$i+2){
if(emptyempty($queryObj[$i])) continue;
if($queryObj[$i]=='symbol'){
$symbol = $queryObj[$i+1];
}
if($queryObj[$i]=='date'){
$date = $queryObj[$i+1];
}
}
}
// 查询列表
$oci = ntes_get_caihui_oci();
$stocklist = array();
$cwsd = new namespace\dao\caihui\Cwsd($oci);
$stockcurror = $cwsd->getCznlList($symbol,$date,$sort,$order,$count*($page),$count);
$sumrecords=$cwsd->getRecordCount($symbol,$date);
$i=0;
//var_dump($symbol,$date,$sort,$order,$count*($page),$count);
foreach($stockcurror as $item){
$item['RSMFRATIO1422']=isset($item['RSMFRATIO1422'])?number_format($item['RSMFRATIO1422'],2).'%':'--';
$item['RSMFRATIO1822']=isset($item['RSMFRATIO1822'])?number_format($item['RSMFRATIO1822'],2).'%':'--';
$item['RSMFRATIO22']=isset($item['RSMFRATIO22'])?number_format($item['RSMFRATIO22'],2).'%':'--';
$item['RSMFRATIO10']=isset($item['RSMFRATIO10'])?number_format($item['RSMFRATIO10'],2):'--';
$item['RSMFRATIO12']=isset($item['RSMFRATIO12'])?number_format($item['RSMFRATIO12'],2):'--';
$item['RSMFRATIO4']=isset($item['RSMFRATIO4'])?number_format($item['RSMFRATIO4'],2):'--';
$item['RSMFRATIO18']=isset($item['RSMFRATIO18'])?number_format($item['RSMFRATIO18'],2):'--';
$item['RSMFRATIO14']=isset($item['RSMFRATIO14'])?number_format($item['RSMFRATIO14'],2):'--';
$item['CODE']=$item['EXCHANGE'].$item['SYMBOL'];
//$item['REPORTDATE']=isset($item['REPORTDATE'])?$item['REPORTDATE']:'--';
$stocklist[$i] = $item;
$i=$i+1;
}
// 输出结果
$result = array();
// 页码page、每页数量count、结果总数total、分页数pagecount、结果列表list
$result['page'] = $page;
$result['count'] = $count;
$result['order'] = $order;
$result['total'] = $i;//$stockcurror->count();
$result['pagecount'] = ceil($sumrecords['SUMRECORD']/$count);
$result['time'] = date('Y-m-d H:i:s');
$result['list'] = $stocklist;
if(emptyempty($callback)){
echo json_encode($result);
}else{
echo $callback.'('.json_encode($result).');';
}
CacherManager::cachePageEnd();
}
?>
下面看一下这个service具体完成的功能:
1. 6-16行,准备缓存参数,开启缓存。
2. 19-41行,提取请求参数。
3. 44-49行,连接、查询数据库。
4. 50-67行,将数据库查询结果放入数组。
5. 71-84行,准备json数据。
6. 86-87行,关闭缓存。
如果只看这一个文件,存在的问题有:
1. 19-86行,没有缩进。
2. 44行,每次请求都会重新连接数据库。
3. 53-61行,重复的逻辑,可以提取为一个函数,然后通过迭代完成。
如果大部分后端Service都采用这个结构,那么问题就是所有的Service都需要经过:开启缓存,取参,获取数据,json转化,关闭缓存这一系列的过程。而在所有过程中,除了获取数据的逻辑,其他的过程都是一样的。在代码中存在着大量的重复逻辑,甚至给人一种“复制-粘贴”的感觉,这严重的违背了DRY原则(Don't Repeat Yourself)。所以,这里需要运用面向对象的思想对其重构。而在我重构的过程中,脑海中始终谨记着一个原则——封装变化原则。所谓封装变化,就是区分系统中不变的和可变的,将可变的进行封装,这样可以很好过应对变化。
通过上面的分析,只有获取数据的逻辑是变化的,其他的逻辑是不变的。所以需要对获取数据的逻辑进行封装,具体的封装方式可以采用继承或组合。我采用的是继承的方式,首先将service的处理过程抽象为:
&n
补充:Web开发 , php ,