• 模板方法模式


    模板方法模式的UML类图入下 :

    解决的问题 :

    • 一些方法通用,但子类重写了很多次
    • 优雅的复用代码

    详细描述:

    • 通用的方法抽出来到父类实现,特殊的行为在子类重写

    注意点:

    • 模板方法通常会加 final

    例子:

    1. 发生告警时,不同的告警(如摄像头告警车辆告警)有相同的方法,如生成告警记录,告警等级提升,关闭告警等都一样,于是可以提升到父类实现。
    2. Java中用了很多
      • AbstractListaddAll()方法
      • InputStreamread(byte b[], int off, int len)方法
      • servlet也是,service()方法是模板方法,子类重写doGetdoPost
      • comparable也是,提供了固定的comparaTo()给子类重写
    3. 个人理解:abstractClass应该都是模板方法模式

    代码:

    1. 父类模板要 抽取公共代码,final修饰

       #ifndef _ALERTTEMPLATE_H 
       #define _ALERTTEMPLATE_H 
        
       #include "../MajiaoObject.hpp" 
      
       // 抽象告警类 
       class AlertTemplate : public MajiaoObject { 
           public :  
               GET_SET(public, string, alertMsg);
               GET_SET(public, string, alertTime);
               GET_SET(public, int, alertLevel);
               GET_SET(public, int, status);
       
               AlertTemplate() {  } 
               AlertTemplate(string msg, string time, int level) :
                   alertMsg(msg), alertTime(time), alertLevel(level)
               {  } 
               ~AlertTemplate() {  } 
               
               // 需要子类重写的模板
               virtual void buildAlert() = 0; 
               virtual void sendAlert() = 0;  
               virtual void callLeaders() = 0;
               virtual void closeAlert() = 0; 
       
               // 父类把不变的东西定死
               virtual void alertHappend() final {
                   this->buildAlert();
                   this->sendAlert();
                   this->callLeaders();
                   this->closeAlert();
               }
               
       }; 
       #endif	// _IALERTTEMPLATE_H
      
      • 实现类A CarAlert重写父类方法,但是不需要改动父类抽取好的方法alertHappend()
       #ifndef _CARALERT_H 
       #define _CARALERT_H 
        
       #include "../AlertTemplate.hpp" 
        
       class CarAlert : public AlertTemplate { 
           public :  
               GET_SET(public, int, loadLimit);
               GET_SET(public, double, v);
               GET_SET(public, int, loadNum);
               GET_SET(public, int64_t, driverId);
               GET_SET(public, string, carNumber);
       
               CarAlert() {  } 
               CarAlert(string carNum) : carNumber(carNum) {  } 
               ~CarAlert() {  } 
       
               // 以下为重写父类的函数
               virtual void buildAlert() override { 
                   this->alertMsg = "车辆【" + carNumber + "】当前人数为";
                   this->alertMsg += loadNum + " 人 ";
               }
               virtual void sendAlert() override {  }
               virtual void callLeaders() override { 
                   callDriver();
               }
               virtual void closeAlert() override { 
                   if (this->loadNum < 10) { 
                       this->setstatus(0);
                   }
               }
       
               // alertHappend()被抽取到父类里了
       
           private :
               void callDriver() {
                   cout << "通知司机" << driverId << "当前车上人数" << endl;
               }
       }; 
       #endif	// _CARALERT_H
      
      • 实现类B CameraAlert,也一样
       #ifndef _CAMERAALERT_H 
       #define _CAMERAALERT_H 
        
       #include "../AlertTemplate.hpp" 
        
       class CameraAlert : public AlertTemplate { 
           public :  
               GET_SET(public, string, cameraName);
               CameraAlert() {  } 
               CameraAlert(string camName) : cameraName(camName) {  }
               ~CameraAlert() {  } 
       
               virtual void buildAlert() { 
                   this->alertMsg = "摄像头" + cameraName + "检测到可以人员进入";
               }
               virtual void sendAlert() {  }
               virtual void callLeaders() { 
                   callAdmin();
               }
               virtual void closeAlert() {  }
       
               // alertHappend()被抽取到父类里了
           private : 
               void callAdmin() {
                   cout << "尝试通知管理员" << endl;
               }
       }; 
       #endif	// _CAMERAALERT_H
      
    2. 在调用方main里,就是普通的使用类即可

      AlertTemplate* alert = new CameraAlert("供电所前门摄像头");
      alert->alertHappend(); // 调用父类抽取的函数
      alert = new CarAlert("桂R8766");
      alert->alertHappend(); // 调用父类抽取的函数
      
  • 相关阅读:
    微信支付-我遇到的那些问题
    [工作笔记]JDK版本不同导致的SSL异常
    mysql与oracle在groupby语句上的细节差异
    微信js-sdk调用
    循序渐进看Java web日志跟踪(3)-Log4J的使用和配置
    循序渐进看Java web日志跟踪(2)-Java日志API认识
    循序渐进看Java web日志跟踪(1)-Tomcat 日志追踪与配置
    手机号码正则表达式(含虚拟运营商)
    网站URL重写(Java UrlRewrite 的使用)
    TCP/IP提供网络传输速率
  • 原文地址:https://www.cnblogs.com/majiao61/p/14998828.html
Copyright © 2020-2023  润新知