模板方法模式

模板方法模式的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(); // 调用父类抽取的函数
    
posted @ 2021-07-11 16:23  马角的逆袭  阅读(23)  评论(0编辑  收藏  举报