Android設計模式之——模板方法模式

一、介紹

在面向對象開發過程中,通常會遇到這樣的一個問題,我們知道一個算法所需的關鍵步驟,并確定了這些步驟的執行順序,但是,某些步驟的具體實現是未知的,或者說某些步驟的實現是會隨著環境的變化而改變的,例如,執行程序的流程大致如下:

  1. 檢查代碼的正確性;
  2. 鏈接相關的類庫;
  3. 編譯相關代碼;
  4. 執行程序。

對于不同的程序設計語言,上述4個步驟都是不一樣的,但是,它們的執行流程是固定的,這類問題的解決方案就是我們本章要講的模板方法模式。

二、定義

定義一個操作中的算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

三、使用場景

  • 多個子類有公有的方法,并且邏輯基本相同時。

  • 重要、復雜的算法,可以把核心算法設計為模板方法,周邊的相關細節功能則由各個子類實現。

  • 重構時,模板方法模式是一個經常使用的模式,把相同的代碼抽取到父類中,然后通過鉤子函數約束其行為。

四、模板方法模式的UML類圖

UML類圖:

這里寫圖片描述

角色介紹:

  • AbstractClass:抽象類,定義了一套算法框架。

  • ConcreteClass1:具體實現類1。

  • ConcreteClass2:具體實現類2。

五、簡單示例

模板方法實際上是封裝一個固定流程,就像是一套執行模板一樣,第一步該做什么,第二步該做什么都已經在抽象類中定義好。而子類可以有不同的算法實現,在框架不被修改的情況下實現某些步驟的算法替換,下面以打開計算機這個動作來簡單演示一下模板方法。打開計算機的整個過程都是相對固定的,首先啟動計算機電源,計算機檢測自身狀態沒有問題時將進入操作系統,對用戶進行驗證之后即可登錄計算機,下面我們使用模板方法來模擬一下這個過程:

抽象的 Computer

/*** 抽象的 Computer*/
public abstract class AbstractComputer {//下面是抽象方法,子類可以覆蓋,不允許外部直接調用這些方法,所以用protected/*** 開啟電源*/protected abstract void powerOn();/*** 檢查硬件*/protected abstract void checkHardware();/*** 載入操作系統*/protected abstract void loadOS();/*** 登錄*/protected abstract void login();//下面是鉤子方法,聲明并實現/*** 是否需要登錄* * @return true為需要登錄*/protected boolean isLogin(){return true;}//下面是模板方法,定義為final,子類不能覆蓋此方法 /*** 啟動計算機方法,步驟為開啟電源、系統檢查、加載系統、檢查是否登錄。*/public final void startUp(){System.out.println("--------開機 START--------");powerOn();checkHardware();loadOS();if(isLogin()){login();}System.out.println("-------- 開機 END --------");}}

Windows系統電腦(不需登錄):

/*** Windows系統電腦*/
public class WindowsComputer extends AbstractComputer{@Overrideprotected void powerOn() {System.out.println("Windows電腦開啟電源");}@Overrideprotected void checkHardware() {System.out.println("Windows電腦檢查硬件");}@Overrideprotected void loadOS() {System.out.println("Windows電腦載入操作系統");}@Overrideprotected void login() {}@Overrideprotected boolean isLogin() {return false;//返回false,不需登錄}}

Mac系統電腦(需登錄):

/*** Mac系統電腦*/
public class MacComputer extends AbstractComputer{@Overrideprotected void powerOn() {System.out.println("Mac電腦開啟電源");}@Overrideprotected void checkHardware() {System.out.println("Mac電腦檢查硬件");}@Overrideprotected void loadOS() {System.out.println("Mac電腦載入操作系統");}@Overrideprotected void login() {System.out.println("Mac電腦登錄");}}

調用:

public class Client {public static void main(String[] args) {AbstractComputer comp = new WindowsComputer();comp.startUp();comp = new MacComputer();comp.startUp();}
}

結果:

--------開機 START--------
Windows電腦開啟電源
Windows電腦檢查硬件
Windows電腦載入操作系統
-------- 開機 END --------
--------開機 START--------
Mac電腦開啟電源
Mac電腦檢查硬件
Mac電腦載入操作系統
Mac電腦登錄
-------- 開機 END --------

六、Android源碼中的模板方法模式

1、AsyncTask

在使用AsyncTask時,我們都知道把耗時操作放到doInBackground(Params… params)中,在doInBackground之前,如果想做一些初始化操作,可以把實現寫在onPreExecute中,當doInBackground執行完后會執行onPostExecute方法,而我們只需要構建AsyncTask對象,然后執行execute方法。

2、Activity的生命周期

ActivityThread的main函數被調用后,依次執行Activity的onCreate、onStart、onResume函數,用戶通常在Activity的子類中覆寫onCreate方法,并且在該方法中調用setContentView來設置布局。

七、區別

  • 工廠方法是模板方法的一種特殊版本。

  • 策略模式和模板方法模式都是封裝算法,一個用組合,一個用繼承。

  • 策略模式和模板模式通常可以互相替換。它們都像試卷,策略模式是選擇題,模板模式是填空題。

八、總結

模板方法模式用4個字概括就是:流程封裝。也就是把某個固定的流程封裝到一個final方法中,并且讓子類能夠定制這個流程中的某些或者所有步驟,這就要求父類提取公用的代碼,提升代碼的復用率,同時帶來了更好的可擴展性。

優點:

  • 封裝不變部分,擴展可變部分。

  • 提取公共部分代碼,便于維護。

缺點:

  • 需要為每一個基本方法的不同實現提供一個子類,如果父類中可變的基本方法太多,將會導致類的個數增加,系統更加龐大,設計也更加抽象,此時,可結合橋接模式來進行設計。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447005.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447005.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447005.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android設計模式之——訪問者模式

一、介紹 訪問者模式是一種將數據操作與數據結構分離的設計模式,它是《設計模式》中23種設計模式中最復雜的一個,但它的使用頻率并不高,正如《設計模式》的作者GOF對訪問者模式的描述:大多數情況下,你不需要使用訪問者…

C++類模板template <class T>簡單使用方法

一個簡單的例子 兩個數比大小 如果兩個數都是int類型 class Compare_int { public :Compare(int a,int b){xa;yb;}int max( ){return (x>y)?x:y;}int min( ){return (x<y)?x:y;} private :int x,y; }; 如果兩個數是float類型 class Compare_float { public :Compare(…

Android設計模式之——中介者模式

一、介紹 中介者模式&#xff08;Mediator Pattern&#xff09;也稱為調解者模式或調停者模式&#xff0c;Mediator本身就有調停者和調解者的意思。 在日常生活中調停者或調解者這個角色我們見得比較多的是“和事老”&#xff0c;也就是說調解兩個有爭端的人的角色&#xff0…

C++智能指針中unique_ptr部分內容的講解

參考鏈接 std::unique_ptr 介紹 定義位于頭文件<memory>std::unique_ptr 是通過指針占有并管理另一對象&#xff0c;并在 unique_ptr 離開作用域時釋放該對象的智能指針。 在下列兩者之一發生時用關聯的刪除器釋放對象&#xff1a;1&#xff0c;銷毀了管理的 unique_pt…

Java基礎——Java多線程中sleep()、wait()和notify()

一、sleep()sleep()方法源碼&#xff1a;/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does …

Key_handle的學習

代碼 一切盡在不言中 #pragma once#include "common/common.h" #include "sdf/sdf.h"#include <memory>namespace sdf {namespace algorithm {class KeyHandle {public:using erased_internal_data_t char; //使用erased_internal_data_t等效于ch…

Java基礎——虛擬機結構

一、Java平臺結構圖二、JVM、JRE和JDK關系JVM&#xff1a;Java Virtual Machine&#xff08;Java虛擬機&#xff09;&#xff0c;負責執行符合規范的Class文件 JRE&#xff1a; Java Runtime Environment &#xff08;java運行環境&#xff09;&#xff0c;包含JVM和類庫 JDK&a…

解決 SSH Connection closed by foreign host 問題

用 Xshell 連接服務器總是報錯 : Connection closed by foreign host.Disconnected from remote host... 原因可能是 SSH 服務器沒設置保活時間間隔 , 具體設置如下 : 操作 # vim /etc/ssh/sshd_config 添加兩行 , 或去掉注釋 : ClientAliveInterval 60ClientAliveCountMax…

Java基礎——synchronized

synchronized重要&#xff01;重要&#xff01;重要&#xff01;重要的事情說三遍&#xff0c;一定要記下來哦。 Java語言的關鍵字&#xff0c;當它用來修飾一個方法或者一個代碼塊的時候&#xff0c;能夠保證在同一時刻最多只有一個線程執行該段代碼。一、當兩個并發線程訪問同…

C++:MAC安裝Boost庫文件并且使用CLion開發

boost的filestem庫 C在17版本的標準庫中引入了一個filesystem庫&#xff0c;用來處理文件路徑&#xff0c;以及文件訪問。很多編譯器對filesystem庫的支持還不是很好。為了解決這個問題&#xff0c;可以臨時使用boost::filesystem來替代。其實C17標準中的filesystem庫就是從bo…

Java基礎——Java異常處理機制

一、引言 try…catch…finally恐怕是大家再熟悉不過的語句了&#xff0c;而且感覺用起來也是很簡單&#xff0c;邏輯上似乎也是很容易理解。不過&#xff0c;我親自體驗的“教訓”告訴我&#xff0c;這個東西可不是想象中的那么簡單、聽話。不信&#xff1f;那你看看下面的代碼…

clion在使用sqlite3的時候,顯示Undefined symbols for architecture x86_64錯誤的解決辦法

顯示Undefined symbols for architecture x86_64錯誤的原因 1、缺少靜態庫 環境&#xff1a;在模擬器上報錯但在真機上能運行成功&#xff0c;而且報的錯誤來自于第三方庫。原因&#xff1a;architecture x86_64 是指模擬器的架構&#xff0c;意思就是 Crypto 變量在模擬器架…

Java基礎——Java反射機制及IoC原理

一、概念 主要是指程序可以訪問&#xff0c;檢測和修改它本身狀態或行為的一種能力&#xff0c;并能根據自身行為的狀態和結果&#xff0c;調整或修改應用所描述行為的狀態和相關的語義。在java中&#xff0c;只要給定類的名字&#xff0c; 那么就可以通過反射機制來獲得類的所…

Ubuntu boost庫文件安裝編譯

簡單介紹 Boost庫是為C語言標準庫提供擴展的一些C程序庫的總稱&#xff0c;由Boost社區組織開發、維護.Boost向來有準標準庫之稱&#xff0c;很多新特性例如智能指針等都是先在boost中實現&#xff0c;后來被吸收到標準庫之中. Boost實現了日志、算法、日期、地理、數學、線程…

Java基礎——類加載機制及原理

一、什么是類的加載&#xff1f; 類的加載指的是將類的.class文件中的二進制數據讀入到內存中&#xff0c;將其放在運行時數據區的方法區內&#xff0c;然后在堆區創建一個java.lang.Class對象&#xff0c;用來封裝類在方法區內的數據結構。類的加載的最終產品是位于堆區中的Cl…

在Ubuntu環境下使用vcpkg安裝sqlite_orm包文件

Ubuntu安裝vcpkg 從github下載vcpkg的安裝包&#xff0c;在usr/local路徑下面執行如下命令 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg //進入源碼目錄 ./bootstrap-vcpkg.sh //執行./bootstrap-vcpkg.sh進行編譯安裝&#xff0c;這個過程很慢 編譯安裝好…

finally語句與return語句的執行順序

網上有很多人探討Java中異常捕獲機制try...catch...finally塊中的finally語句是不是一定會被執行&#xff1f;很多人都說不是&#xff0c;當然他們的回答是正確的&#xff0c;經過我試驗&#xff0c;至少有兩種情況下finally語句是不會被執行的&#xff1a; try語句沒有被執行到…

window電腦查看ssh公鑰,以及將自己的公鑰添加到Github等類似網站

查看本機的ssh公鑰 使用命令 cd ~/.ssh使用命令 ls 可以看到 id_rsa id_rsa.pub known_hosts 三個文件&#xff0c;此處需要的是id_rsa.pub文件使用命令 cat id_rsa.pub 查看文件的內容拷貝這段內容 添加自己的公鑰 進入賬戶的設置頁面參照如下步驟&#xff0c;進入SSH Key…

java八大排序算法

一、概述 排序有內部排序和外部排序&#xff0c;內部排序是數據記錄在內存中進行排序&#xff0c;而外部排序是因排序的數據很大&#xff0c;一次不能容納全部的排序記錄&#xff0c;在排序過程中需要訪問外存。 我們這里說說八大排序就是內部排序。 當n較大&#xff0c;則應采…

密鑰安全性討論之密鑰分層管理結構

密鑰分層管理結構 密鑰的安全管理通常采用層次化的保護方法。密鑰管理分層管理機制將密鑰分為三層&#xff0c;即根密鑰、密鑰加密密鑰和工作密鑰下層密鑰為上層密鑰提供加密保護&#xff0c;采用分層的密鑰結構有助于密鑰的管理滿足本規范的要求 工作密鑰 工作密鑰對本地保存…