設計模式——行為型模式(一)

行為型模式用于描述程序在運行時復雜的流程控制,即描述多個類或對象之間怎樣相互協作共同完成單個對象都無法單獨完成的任務,它涉及算法與對象間職責的分配

行為型模式分為類行為模式和對象行為模式,前者采用繼承機制來在類間分派行為,后者采用組合或聚合在對象間分配行為。由于組合關系或聚合關系比繼承關系耦合度低,滿足“合成復用原則”,所以對象行為模式比類行為模式具有更大的靈活性。

行為型模式分為:

  • 模板方法模式
  • 策略模式
  • 命令模式
  • 職責鏈模式
  • 狀態模式
  • 觀察者模式
  • 中介者模式
  • 迭代器模式
  • 訪問者模式
  • 備忘錄模式
  • 解釋器模式

以上 11 種行為型模式,除了模板方法模式和解釋器模式是類行為型模式,其他的全部屬于對象行為型模式。

6.1 模板方法模式

6.1.1 概述

在面向對象程序設計過程中,程序員常常會遇到這種情況:設計一個系統時知道了算法所需的關鍵步驟,而且確定了這些步驟的執行順序,但某些步驟的具體實現還未知,或者說某些步驟的實現與具體的環境相關。

例如,去銀行辦理業務一般要經過以下4個流程:取號、排隊、辦理具體業務、對銀行工作人員進行評分等,其中取號、排隊和對銀行工作人員進行評分的業務對每個客戶是一樣的,可以在父類中實現,但是辦理具體業務卻因人而異,它可能是存款、取款或者轉賬等,可以延遲到子類中實現。

定義:

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

6.1.2 結構

模板方法(Template Method)模式包含以下主要角色:

  • 抽象類(Abstract Class):負責給出一個算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。

    • 模板方法:定義了算法的骨架,按某種順序調用其包含的基本方法。

    • 基本方法:是實現算法各個步驟的方法,是模板方法的組成部分。基本方法又可以分為三種:

      • 抽象方法(Abstract Method) :一個抽象方法由抽象類聲明、由其具體子類實現。

      • 具體方法(Concrete Method) :一個具體方法由一個抽象類或具體類聲明并實現,其子類可以進行覆蓋也可以直接繼承。

      • 鉤子方法(Hook Method) :在抽象類中已經實現,包括用于判斷的邏輯方法和需要子類重寫的空方法兩種。

        一般鉤子方法是用于判斷的邏輯方法,這類方法名一般為isXxx,返回值類型為boolean類型。

  • 具體子類(Concrete Class):實現抽象類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的組成步驟。

6.1.3 案例實現

【例】炒菜

炒菜的步驟是固定的,分為倒油、熱油、倒蔬菜、倒調料品、翻炒等步驟。現通過模板方法模式來用代碼模擬。類圖如下:

代碼如下:

abstract class AbstractClass {//模板方法,為防止惡意操作,一般模板方法都加上 final 關鍵詞。public final void cookProcess() {//第一步:倒油this.pourOil();//第二步:熱油this.heatOil();//第三步:倒蔬菜this.pourVegetable();//第四步:倒調味料this.pourSauce();//第五步:翻炒this.fry();}public void pourOil() {System.out.println("倒油");}//第二步:熱油是一樣的,所以直接實現public void heatOil() {System.out.println("熱油");}//第三步:倒蔬菜是不一樣的(一個下包菜,一個是下菜心)public abstract void pourVegetable();//第四步:倒調味料是不一樣public abstract void pourSauce();//第五步:翻炒是一樣的,所以直接實現public void fry(){System.out.println("炒啊炒啊炒到熟啊");}
}
class ConcreteClass_BaoCai extends AbstractClass {@Overridepublic void pourVegetable() {System.out.println("下鍋的蔬菜是包菜");}@Overridepublic void pourSauce() {System.out.println("下鍋的醬料是辣椒");}
}
class ConcreteClass_CaiXin extends AbstractClass {@Overridepublic void pourVegetable() {System.out.println("下鍋的蔬菜是菜心");}@Overridepublic void pourSauce() {System.out.println("下鍋的醬料是蒜蓉");}
}
public class Client {public static void main(String[] args) {//炒手撕包菜ConcreteClass_BaoCai baoCai = new ConcreteClass_BaoCai();baoCai.cookProcess();//炒蒜蓉菜心ConcreteClass_CaiXin caiXin = new ConcreteClass_CaiXin();caiXin.cookProcess();}
}

倒油
熱油
下鍋的蔬菜是包菜
下鍋的醬料是辣椒
炒啊炒啊炒到熟啊
倒油
熱油
下鍋的蔬菜是菜心
下鍋的醬料是蒜蓉
炒啊炒啊炒到熟啊

6.1.3 優缺點

優點:

  • 提高代碼復用性

    將相同部分的代碼放在抽象的父類中,而將不同的代碼放入不同的子類中。

  • 實現了反向控制

    通過一個父類調用其子類的操作,通過對子類的具體實現擴展不同的行為,實現了反向控制 ,并符合“開閉原則”。

缺點:

  • 對每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象。
  • 父類中的抽象方法由子類實現,子類執行的結果會影響父類的結果,這導致一種反向的控制結構,它提高了代碼閱讀的難度

6.1.4 適用場景

  • 算法的整體步驟很固定,但其中個別部分易變時,這時候可以使用模板方法模式,將容易變的部分抽象出來,供子類實現。
  • 需要通過子類來決定父類算法中某個步驟是否執行,實現子類對父類的反向控制

6.2 策略模式

6.2.1 概述

先看下面的圖片,我們去旅游選擇出行模式有很多種,可以騎自行車、可以坐汽車、可以坐火車、可以坐飛機。

作為一個程序猿,開發需要選擇一款開發工具,當然可以進行代碼開發的工具有很多,可以選擇Idea進行開發,也可以使用eclipse進行開發,也可以使用其他的一些開發工具。

定義:

該模式定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬于對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,并委派給不同的對象對這些算法進行管理。

6.2.2 結構

策略模式的主要角色如下:

  • 抽象策略(Strategy)類:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
  • 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現或行為。
  • 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。

6.2.3 案例實現

【例】促銷活動

一家百貨公司在定年度的促銷活動。針對不同的節日(春節、中秋節、圣誕節)推出不同的促銷活動,由促銷員將促銷活動展示給客戶。類圖如下:

//抽象策略類
interface Strategy {void show();
}
//具體策略類,為春節準備的促銷活動A
class StrategyA implements Strategy {public void show() {System.out.println("買一送一");}
}
//為中秋準備的促銷活動B
class StrategyB implements Strategy {public void show() {System.out.println("滿200元減50元");}
}
//為圣誕準備的促銷活動C
class StrategyC implements Strategy {public void show() {System.out.println("滿1000元加一元換購任意200元以下商品");}
}
//環境類
class SalesMan {//持有抽象策略角色的引用private Strategy strategy;public SalesMan(Strategy strategy) {this.strategy = strategy;}//向客戶展示促銷活動public void salesManShow() {strategy.show();}
}
class Test {public static void main(String[] args) {Strategy strategy = new StrategyB();SalesMan salesMan = new SalesMan(strategy);salesMan.salesManShow();}
}

6.2.4 優缺點

1,優點:

  • 策略類之間可以自由切換

    由于策略類都實現同一個接口,所以使它們之間可以自由切換

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

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

相關文章

醫院預約管理系統開發 代碼展示 九價疫苗接種預約功能(含小程序源代碼)

基于微信小程序的疫苗預約系統讓疫苗信息,疫苗預約信息等相關信息集中在后臺讓管理員管理,讓用戶在小程序端預約疫苗,查看疫苗預約信息,該系統讓信息管理變得高效,也讓用戶預約疫苗,查看疫苗預約等信息變得…

MySQL 優化器 Index Condition Pushdown下推(ICP)

ICP 測試 準備數據 CREATE TABLE icp (employee_id int(6) NOT NULL AUTO_INCREMENT,first_name varchar(20) DEFAULT NULL,last_name varchar(25) DEFAULT NULL,email varchar(25) DEFAULT NULL,phone_number varchar(20) DEFAULT NULL,PRIMARY KEY (employee_id) );insert i…

額溫槍方案,MS8551,MS8601;MS1112,MS1100

鑒于測溫的傳感器信號非常微弱,需要用高精度、低噪聲的運算放大器和高精度、低功耗的ADC。 運算放大器可供選擇:MS8551 or MS8601,具有低失調(1uV)、低噪(22nV√Hz )、封裝小等優點&#xff0c…

Redis并發問題解決方案

目錄 前言 1.分布式鎖 1.基于單個節點 2.基于多個節點 3.watch(樂觀鎖) 2.原子操作 1.單命令操作 2.Lua 腳本(多命令操作) 3.事務 1.執行步驟 2.錯誤處理 3.崩潰處理 總結 前言 在多個客戶端并發訪問Redis的時候,雖然Redis是單線程執行指令&#xff…

【間歇振蕩器2片555時基仿真】2022-9-24

緣由multisim出現這個應該怎么解決吖,急需解決-嵌入式-CSDN問答 輸出一定要有電阻分壓才能前后連接控制否則一定報錯。

Python自動化生成漂亮的測試報告

📢專注于分享軟件測試干貨內容,歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!📢交流討論:歡迎加入我們一起學習!📢資源分享:耗時200小時精選的「軟件測試」資…

五種多目標優化算法(MOJS、NSGA3、MOGWO、NSWOA、MOPSO)求解微電網多目標優化調度(MATLAB代碼)

一、多目標優化算法簡介 (1)多目標水母搜索算法MOJS 多目標優化算法:多目標水母搜索算法MOJS(提供MATLAB代碼)_水母算法-CSDN博客 (2)NSGA3 NSGA-III求解微電網多目標優化調度(M…

acwing算法基礎之數學知識--求卡特蘭數

目錄 1 基礎知識2 模板3 工程化 1 基礎知識 題目:給定n個0和n個1,它們將按照某種順序排成長度為2n的序列,求它們能排成的所有序列中,能夠滿足任意前綴序列中0的個數都不少于1的個數的序列有多少個? 輸出的答案對 1 0 …

【云原生 Prometheus篇】Prometheus的動態服務發現機制與認證配置

目錄 一、Prometheus服務發現的方式1.1 基于文件的服務發現1.2 基于consul的服務發現1.3 基于 Kubernetes API 的服務發現1.3.1 簡介1.3.2 基于Kurbernetes發現機制的部分配置參數 二、實例一:部署基于文件的服務發現2.1 創建用于服務發現的文件2.2 修改Prometheus的…

yo!這里是c++11重點新增特性介紹

目錄 前言 列表初始化 { }初始化 initializer_list類 類型推導 auto decltype 范圍for 右值引用與移動語義 左值引用和右值引用 移動語義 1.移動構造 2.移動賦值 3.stl容器相關更新 右值引用和萬能引用 完美轉發 關鍵字 default delete final和override …

西米支付:簡單介紹一下支付公司的分賬功能體系

隨著互聯網的普及和電子商務的快速發展,支付已經成為人們日常生活的重要組成部分。支付公司作為第三方支付平臺,為消費者和商家提供了便捷、安全的支付方式。而在支付領域中,分賬功能是一個非常重要的功能,它可以幫助企業實現資金…

SpringBoot——攔截器

優質博文:IT-BLOG-CN 一、登錄時可能會出現重復提交問題。我們可以通過重定向解決此問題。例如:用戶提交的請求為:/user/login,通過redirect:重定向至 main.html請求。 PostMapping("/user/login") public …

C語言——從終端(鍵盤)將 5 個整數輸入到數組 a 中,然后將 a 逆序復制到數組 b 中,并輸出 b 中 各元素的值。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i;int a[5];int b[5];printf("輸入5個整數&#xff1a;\n");for(i0;i<5;i){scanf("%d",&a[i]);}printf("數組b的元素值為&#xff1a;\n");for(i4;i>0;i--…

Windows任務管理器內存性能界面各個參數含義

任務管理器的內存性能界面提供了一些關鍵參數&#xff0c;這些參數可以幫助你了解系統中內存的使用情況。以下是一些常見的參數及其含義&#xff1a; 已提交&#xff08;Committed&#xff09;&#xff1a; 表示已分配的物理內存和虛擬內存的總和。已提交的內存包括當前正在使…

Javascript每天一道算法題(十五)——輪轉數組_中等(一行解決輪轉數組)

文章目錄 1、問題2、示例3、解決方法&#xff08;1&#xff09;方法1——while遍歷&#xff08;較為復雜&#xff0c;不推薦&#xff09;&#xff08;2&#xff09;方法2&#xff08;直接截取后插入&#xff0c;推薦&#xff09;&#xff08;3&#xff09;方法3——優化方法2&a…

jQuery_03 dom對象和jQuery對象的互相轉換

dom對象和jQuery對象 dom對象 jQuery對象 在一個文件中同時存在兩種對象 dom對象: 通過js中的document對象獲取的對象 或者創建的對象 jQuery對象: 通過jQuery中的函數獲取的對象。 為什么使用dom或jQuery對象呢&#xff1f; 目的是 要使用dom對象的函數或者屬性 以及呢 要…

python -opencv 輪廓檢測(多邊形,外接矩形,外接圓)

python -opencv 輪廓檢測(多邊形&#xff0c;外接矩形&#xff0c;外接圓) 邊緣檢測步驟: 第一步&#xff1a;讀取圖像為灰度圖 第二步&#xff1a;進行二值化處理 第三步&#xff1a;使用cv2.findContours對二值化圖像提取輪廓 第三步&#xff1a;將輪廓繪制到圖中 代碼如下…

Hibernate的三種狀態

1.瞬時狀態(Transient) 通過new創建對象后&#xff0c;對象并沒有立刻持久化&#xff0c;他并未對數據庫中的數據有任何的關聯&#xff0c;此時java對象的狀態為瞬時狀態&#xff0c;Session對于瞬時狀態的java對象是一無所知的&#xff0c;當對象不再被其他對象引用時&#xf…

【TL431+場效應管組成過壓保護電路】2022-3-22

緣由這個穩壓三極管是構成的電路是起到保護的作用嗎&#xff1f;-硬件開發-CSDN問答

HTML5+ API 爬坑記錄

背景: 有個比較早些使用5開發的項目, 最近兩天反饋了一些問題, 解決過程在此記錄; 坑1: plus.gallery.pick 選擇圖片沒有進入回調 HTML5 API Reference 在 聯想小新 平板電腦上選擇相冊圖片進行上傳時, 打開相冊瞬間 應用會自動重啟, 相冊倒是有打開, 不過應用重啟了, 導…