Maison développement back-end tutoriel php php重构优化一例——模板方法模式应用_PHP教程

php重构优化一例——模板方法模式应用_PHP教程

Jul 13, 2016 pm 05:48 PM
php 优化 exister 应用 方法 模式 模板 经验 重构 项目

 最近优化php项目,记录下经验,直接上干活。。。

        php在公司项目中主要用于页面展现,前端有个view,view向后端的service请求数据,数据的传输格式是json。下面看优化前的service的代码:

[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     $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         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的处理过程抽象为:
        service(){
                startCache();
                getParam();
                getData(); // 抽象方法,由子类实现
                toJson();
                closeCache();
        }
         抽象出ServiceBase类,由子类继承,实现相应的获取数据的逻辑,子类不需要处理其他的取参、缓存等逻辑,这些都被ServiceBase类处理了。
[php]
abstract class ServiceBase {         
    public function __construct($cache_path, $cache_type, $max_age, $age_explore) { 
        // 获取请求参数 
        $this->page = $this->getQueryParamDefault('page', 0, INT); 
        // 省略其他的获取参数的逻辑 
        ……       
 
        // 生成响应 
        $this->response(); 
    } 
 
    /**
     * 
     * 子类实现,返回数组格式的数据
     */ 
    abstract protected function data(); 
 
    /**
     * 
     * 子类实现,返回所有数据的总数
     */ 
    abstract protected function total(); 
 
    private function cache() { 
        $url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; 
        $url_hash = md5($url); 
        $key = $this->cache_path.$url_hash.'.json'; 
        if(!CacherManager::cachePageStart($this->cache_type, $key, $this->age_cache)){ 
            $this->no_cache(); 
            CacherManager::cachePageEnd(); 
        } 
    } 
 
    private function no_cache(){ 
        $data = $this->data(); 
        $total = $this->total(); 
        $this->send_data($data, $total); 
    } 
 
    private function send_data($data, $total){ 
        // 进行json转化,省略具体代码 
    } 
 
    private function response() { 
        header('Content-type: text/plain; charset=utf-8'); 
        header('Cache-Control: max-age='.$this->age_explore);     
        if($this->cache_type == NONE || self::$enable_cache == false){ 
            $this->no_cache(); 
        }else{ 
            $this->cache(); 
        } 
    } 

        这就是各个service的抽象父类,有两个抽象方法data和total,data是返回数组格式的数据,tatol是由于分页加入的。具体的service只要继承ServiceBase并实现data和total方法即可,其他的逻辑都是复用的父类的。实际上,优化后的ServiceBase是使用了模板方法模式(Template Method),父类定义算法处理的流程(service的处理过程),子类实现某个具体变化的步骤(具体service的获取数据的逻辑)。通过使用模板方法模式可以保证步骤的变化对于客户端是透明的,并且可以复用父类中的逻辑。

        下面是上述php采用ServiceBase后的代码:

[php]
class CWSDService extends ServiceBase{ 
    function __construct(){ 
        parent::__construct(); 
        $oci = ntes_get_caihui_oci(); 
        $this->$cwsd = new namespace\dao\caihui\Cwsd($oci); 
    } 
    public function data(){ 
        $stocklist = array(); 
        $stockcurror = $this->cwsd->getCznlList($this->query_obj['symbol'],  
            $this->query_obj['symbol'], $sort, $order, $count*($page), $count); 
        $filter_list = array('RSMFRATIO1422', 'RSMFRATIO1822', 'RSMFRATIO22', 
            'RSMFRATIO10', 'RSMFRATIO12', 'RSMFRATIO4', 'RSMFRATIO18', 
            'RSMFRATIO14'); 
        $i=0; 
        foreach($stockcurror as $item){ 
            foreach($filter_list as $k) 
                $this->filter($item, $k); 
            $item['CODE']=$item['EXCHANGE'].$item['SYMBOL']; 
            $stocklist[$i] = $item; 
            $i=$i+1; 
        } 
        return $stocklist; 
    } 
    public function total(){ 
        return $sumrecords=$this->cwsd->getRecordCount($this->query_obj['symbol'],  
            $this->query_obj['symbol']); 
    } 
    private function filter($item, $k){ 
        isset($item[$k])?number_format($item[$k],2).'%':'--'; 
    } 

new CWSDService('/finance/hs/realtimedata/market/ab', MONGO, 30, 30); 
 代码量从87减少到32行,是因为大部分的逻辑都由父类完成,具体service只需要关注自己的业务逻辑就可以了。通过上面代码可以看出继承可以实现代码复用,多个子类中的相同的逻辑可以提取到父类中达到复用的目的;同时,继承也增加了父类和子类之间的耦合性,这也就是组合由于继承的方面,如果这个例子采用组合来封装变化,则具体的实现就是策略模式,将具体获取数据的逻辑看成是策略,不同的service就是不同的策略,由于时间原因,不再赘述。。。

摘自 chosen0ne的专栏
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/478442.htmlTechArticle最近优化php项目,记录下经验,直接上干活。。。 php在公司项目中主要用于页面展现,前端有个view,view向后端的service请求数据,数据的传...
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 apporte plusieurs nouvelles fonctionnalités, améliorations de sécurité et de performances avec une bonne quantité de dépréciations et de suppressions de fonctionnalités. Ce guide explique comment installer PHP 8.4 ou mettre à niveau vers PHP 8.4 sur Ubuntu, Debian ou leurs dérivés. Bien qu'il soit possible de compiler PHP à partir des sources, son installation à partir d'un référentiel APT comme expliqué ci-dessous est souvent plus rapide et plus sécurisée car ces référentiels fourniront les dernières corrections de bogues et mises à jour de sécurité à l'avenir.

7 fonctions PHP que je regrette de ne pas connaître auparavant 7 fonctions PHP que je regrette de ne pas connaître auparavant Nov 13, 2024 am 09:42 AM

Si vous êtes un développeur PHP expérimenté, vous aurez peut-être le sentiment d'y être déjà allé et de l'avoir déjà fait. Vous avez développé un nombre important d'applications, débogué des millions de lignes de code et peaufiné de nombreux scripts pour réaliser des opérations.

Comment configurer Visual Studio Code (VS Code) pour le développement PHP Comment configurer Visual Studio Code (VS Code) pour le développement PHP Dec 20, 2024 am 11:31 AM

Visual Studio Code, également connu sous le nom de VS Code, est un éditeur de code source gratuit – ou environnement de développement intégré (IDE) – disponible pour tous les principaux systèmes d'exploitation. Avec une large collection d'extensions pour de nombreux langages de programmation, VS Code peut être c

Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Apr 05, 2025 am 12:04 AM

JWT est une norme ouverte basée sur JSON, utilisée pour transmettre en toute sécurité des informations entre les parties, principalement pour l'authentification de l'identité et l'échange d'informations. 1. JWT se compose de trois parties: en-tête, charge utile et signature. 2. Le principe de travail de JWT comprend trois étapes: la génération de JWT, la vérification de la charge utile JWT et l'analyse. 3. Lorsque vous utilisez JWT pour l'authentification en PHP, JWT peut être généré et vérifié, et les informations sur le rôle et l'autorisation des utilisateurs peuvent être incluses dans l'utilisation avancée. 4. Les erreurs courantes incluent une défaillance de vérification de signature, l'expiration des jetons et la charge utile surdimensionnée. Les compétences de débogage incluent l'utilisation des outils de débogage et de l'exploitation forestière. 5. L'optimisation des performances et les meilleures pratiques incluent l'utilisation des algorithmes de signature appropriés, la définition des périodes de validité raisonnablement,

Comment analysez-vous et traitez-vous HTML / XML dans PHP? Comment analysez-vous et traitez-vous HTML / XML dans PHP? Feb 07, 2025 am 11:57 AM

Ce tutoriel montre comment traiter efficacement les documents XML à l'aide de PHP. XML (Language de balisage extensible) est un langage de balisage basé sur le texte polyvalent conçu à la fois pour la lisibilité humaine et l'analyse de la machine. Il est couramment utilisé pour le stockage de données et

Programme PHP pour compter les voyelles dans une chaîne Programme PHP pour compter les voyelles dans une chaîne Feb 07, 2025 pm 12:12 PM

Une chaîne est une séquence de caractères, y compris des lettres, des nombres et des symboles. Ce tutoriel apprendra à calculer le nombre de voyelles dans une chaîne donnée en PHP en utilisant différentes méthodes. Les voyelles en anglais sont a, e, i, o, u, et elles peuvent être en majuscules ou en minuscules. Qu'est-ce qu'une voyelle? Les voyelles sont des caractères alphabétiques qui représentent une prononciation spécifique. Il y a cinq voyelles en anglais, y compris les majuscules et les minuscules: a, e, i, o, u Exemple 1 Entrée: String = "TutorialSpoint" Sortie: 6 expliquer Les voyelles dans la chaîne "TutorialSpoint" sont u, o, i, a, o, i. Il y a 6 yuans au total

Expliquez la liaison statique tardive en PHP (statique: :). Expliquez la liaison statique tardive en PHP (statique: :). Apr 03, 2025 am 12:04 AM

Liaison statique (statique: :) ​​implémente la liaison statique tardive (LSB) dans PHP, permettant à des classes d'appel d'être référencées dans des contextes statiques plutôt que de définir des classes. 1) Le processus d'analyse est effectué au moment de l'exécution, 2) Recherchez la classe d'appel dans la relation de succession, 3) il peut apporter des frais généraux de performance.

Quelles sont les méthodes PHP Magic (__construct, __ destruct, __ call, __get, __set, etc.) et fournir des cas d'utilisation? Quelles sont les méthodes PHP Magic (__construct, __ destruct, __ call, __get, __set, etc.) et fournir des cas d'utilisation? Apr 03, 2025 am 12:03 AM

Quelles sont les méthodes magiques de PHP? Les méthodes magiques de PHP incluent: 1. \ _ \ _ Construct, utilisé pour initialiser les objets; 2. \ _ \ _ Destruct, utilisé pour nettoyer les ressources; 3. \ _ \ _ Appel, gérer les appels de méthode inexistants; 4. \ _ \ _ GET, Implémentez l'accès à l'attribut dynamique; 5. \ _ \ _ SET, Implémentez les paramètres d'attribut dynamique. Ces méthodes sont automatiquement appelées dans certaines situations, améliorant la flexibilité et l'efficacité du code.

See all articles