【設計模式——學習筆記】23種設計模式——中介者模式Mediator(原理講解+應用場景介紹+案例介紹+Java代碼實現)

文章目錄

  • 案例引入
    • 案例一
      • 普通實現
      • 中介者模式
    • 案例二
  • 介紹
    • 基礎介紹
    • 登場角色
      • 尚硅谷
    • 《圖解設計模式》
  • 案例實現
    • 案例一:智能家庭
      • 類圖
      • 實現
    • 案例二:登錄頁面邏輯實現
      • 說明
      • 類圖
      • 實現
  • 總結
  • 文章說明

案例引入

案例一

普通實現

在租房過程中,客戶可能去找房東問房子是否可以租,但是房東可能要和家人進行一系列的溝通,最后還可能派出另一個家庭成員來和客戶進行交流,整個溝通過程非常復雜、溝通線路繁多。如果是寫成程序的模式,不同成員之間需要留好接口方便成員之間互相進行調用

在這里插入圖片描述

【分析】

  • 各個成員彼此聯系,你中有我,我中有你,不利于松耦合
  • 各個成員之間所傳遞的消息(參數)容易混亂
  • 當系統增加一個新的成員時,或者執行流程改變時,代碼的可維護性、擴展性都不理想

【改進】

  • 使用中介者模式

中介者模式

客戶只需要對接中介,其他成員互相之間不進行溝通,由中介來進行溝通。如 屋主—>爸爸 變成 屋主—>中介—>爸爸。通過中介的聯絡,可以將成員之間的關聯關系都搞定
在這里插入圖片描述

案例二

現在很多家庭都配備了智能家居,包括各種設備,如鬧鐘、咖啡機、電視機、窗簾……

當主人想要看電視時,會讓多個設備協同工作,來自動完成看電視的準備工作,比如流程為: 鬧鈴響起->咖啡機開始做咖啡->窗簾自動落下->電視機開始播放

介紹

基礎介紹

  • 在中介者模式中,團隊組員之間不再互相溝通并私自做出決定,而是發生任何事情都向中介者報告,中介者站在整個團隊的角度上對組員上報的事情做出決定。當中介者下達指示時,組員會立即執行
  • 用一個中介對象來封裝一系列的對象交互方法。中介者使各個對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互
  • 中介者模式屬于行為型模式
  • 在MVC模式中,C(Controller控制器) 是M(Model模型) 和V(View視圖)的中介者,在前后端交互時起到了中間人的作用

在這里插入圖片描述

登場角色

尚硅谷

在這里插入圖片描述

  • Mediator 就是抽象中介者,定義了同事對象到中介者對象的接口
  • Colleague 是抽象同事類
  • ConcreteMediator 具體的中介者對象,實現抽象方法,他需要知道所有的具體同事類,即以HashMap管理所有同事類,并接受某個同事對象的消息,來協調其他同事完成相應的任務
  • ConcreteColleague 具體的同事類,可能會有很多個,每個同事只知道自己的行為,而不了解其他同事類的行為(方法),他們都依賴中介者對象

《圖解設計模式》

在這里插入圖片描述

  • Mediator(仲裁者、中介者):負責定義與 Colleague 角色進行通信和做出決定的接口(API)
  • ConcreteMediator(具體的仲裁者、中介者):負責實現 Mediator 角色的接口(API),負責實際上如何做出決定
  • Colleague(同事):負責定義與Mediator角色進行通信的接口(API)
  • ConcreteColleague(具體的同事):負責實現 Colleague 角色的接口(API)

案例實現

案例一:智能家庭

類圖

在這里插入圖片描述

【操作流程】

  • 創建 ConcreteMediator 對象
  • 創建各個同事類對象,比如: Alarm、CoffeeMachine、TV
  • 在創建同事類對象的時候,就直接通過構造器,加入到 colleagueMap
  • 同事類對象,可以調用sendMessage,最終會去調用ConcreteMediator的getMessage方法
  • getMessage(核心方法)會根據接收到的同事對象發出的消息 來協調調用其它的同事對象來共同完成任務

實現

【抽象中介者類】

package com.atguigu.mediator.smarthouse;public abstract class Mediator {/*** 將給中介者對象,加入到集合中* @param colleagueName* @param colleague*/public abstract void register(String colleagueName, Colleague colleague);/*** 接收消息, 具體的同事對象發出* @param stateChange* @param colleagueName*/public abstract void getMessage(int stateChange, String colleagueName);public abstract void sendMessage();
}

【具體中介者類】

package com.atguigu.mediator.smarthouse;import java.util.HashMap;/*** 具體的中介者類*/
public class ConcreteMediator extends Mediator {/*** 集合,放入所有的同事對象*/private HashMap<String, Colleague> colleagueMap;private HashMap<String, String> interMap;public ConcreteMediator() {colleagueMap = new HashMap<String, Colleague>();interMap = new HashMap<String, String>();}@Overridepublic void register(String colleagueName, Colleague colleague) {colleagueMap.put(colleagueName, colleague);if (colleague instanceof Alarm) {interMap.put("Alarm", colleagueName);} else if (colleague instanceof CoffeeMachine) {interMap.put("CoffeeMachine", colleagueName);} else if (colleague instanceof TV) {interMap.put("TV", colleagueName);} else if (colleague instanceof Curtains) {interMap.put("Curtains", colleagueName);}}/*** 具體中介者的核心方法* 1. 根據得到消息,完成對應任務* 2. 中介者在這個方法,協調各個具體的同事對象,完成任務* @param stateChange* @param colleagueName*/@Overridepublic void getMessage(int stateChange, String colleagueName) {//處理鬧鐘發出的消息if (colleagueMap.get(colleagueName) instanceof Alarm) {if (stateChange == 0) {// 老司機做咖啡((CoffeeMachine) (colleagueMap.get(interMap.get("CoffeeMachine")))).StartCoffee();// 啟動電視((TV) (colleagueMap.get(interMap.get("TV")))).StartTv();} else if (stateChange == 1) {// 關掉電視((TV) (colleagueMap.get(interMap.get("TV")))).StopTv();}} else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) {// 將窗簾升起來((Curtains) (colleagueMap.get(interMap.get("Curtains")))).UpCurtains();} else if (colleagueMap.get(colleagueName) instanceof TV) {//如果TV發現消息} else if (colleagueMap.get(colleagueName) instanceof Curtains) {//如果是以窗簾發出的消息,這里處理...}}@Overridepublic void sendMessage() {}}

【抽象同事類:Colleague】

package com.atguigu.mediator.smarthouse;/*** 抽象同事類*/
public abstract class Colleague {/*** 關聯 Mediator*/private Mediator mediator;public String name;public Colleague(Mediator mediator, String name) {this.mediator = mediator;this.name = name;}public Mediator GetMediator() {return this.mediator;}public abstract void SendMessage(int stateChange);
}

【具體同事類:鬧鐘】

package com.atguigu.mediator.smarthouse;/*** 具體的同事類 鬧鐘*/
public class Alarm extends Colleague {/*** 構造器* @param mediator* @param name*/public Alarm(Mediator mediator, String name) {super(mediator, name);//在創建Alarm 同事對象時,將自己放入到ConcreteMediator 對象的集合中mediator.register(name, this);}public void SendAlarm(int stateChange) {SendMessage(stateChange);}@Overridepublic void SendMessage(int stateChange) {//調用的中介者對象的getMessagethis.GetMediator().getMessage(stateChange, this.name);}}

【具體同事類:窗簾】

package com.atguigu.mediator.smarthouse;/*** 窗簾*/
public class Curtains extends Colleague {public Curtains(Mediator mediator, String name) {super(mediator, name);mediator.register(name, this);}@Overridepublic void SendMessage(int stateChange) {this.GetMediator().getMessage(stateChange, this.name);}public void UpCurtains() {System.out.println("I am holding Up Curtains!");}}

【具體同事類:電視】

package com.atguigu.mediator.smarthouse;public class TV extends Colleague {public TV(Mediator mediator, String name) {super(mediator, name);mediator.register(name, this);}@Overridepublic void SendMessage(int stateChange) {this.GetMediator().getMessage(stateChange, this.name);}public void StartTv() {System.out.println("It's time to StartTv!");}public void StopTv() {System.out.println("StopTv!");}
}

【主類】

package com.atguigu.mediator.smarthouse;public class ClientTest {public static void main(String[] args) {//創建一個中介者對象Mediator mediator = new ConcreteMediator();//創建Alarm并且加入到 ConcreteMediator 對象的HashMapAlarm alarm = new Alarm(mediator, "alarm");//創建了CoffeeMachine對象,并且加入到 ConcreteMediator 對象的HashMapCoffeeMachine coffeeMachine = new CoffeeMachine(mediator,"coffeeMachine");//創建 Curtains, 并且加入到 ConcreteMediator 對象的HashMapCurtains curtains = new Curtains(mediator, "curtains");TV tV = new TV(mediator, "TV");//讓鬧鐘發出消息alarm.SendAlarm(0);//做好咖啡coffeeMachine.FinishCoffee();alarm.SendAlarm(1);}}

【運行】

It's time to startcoffee!
It's time to StartTv!
After 5 minutes!
Coffee is ok!
I am holding Up Curtains!
StopTv!Process finished with exit code 0

【分析】

  • 程序拓展性較好:如果添加一個機器,只需要添加一個 ConcreteColleague 并修改 ConcreteMediator 的相關方法就行,客戶端不用改變

案例二:登錄頁面邏輯實現

說明

在這里插入圖片描述

需要實現一個系統登錄表單功能,具體的處理邏輯如下:

  • 如果選擇作為游客訪問,那么禁用用戶名輸入框和密碼輸入框,使用戶無法輸入
  • 如果選擇作為用戶登錄,那么啟用用戶名輸入框和密碼輸入框,使用戶可以輸入
  • 如果在用戶名輸入框中一個字符都沒有輸入,那么禁用密碼輸入框,使用戶無法輸入密碼
  • 如果在用戶名輸入框中輸入了至少一個字符,那么啟用密碼輸入框,使用戶可以輸入密碼(當然,如果選擇作為游客訪問,那么密碼框依然是禁用狀態 )
  • 只有當用戶名輸入框和密碼輸入框中都至少輸入一個字符后,OK 按鈕才處于啟用狀態,可以被按下
  • 用戶名輸入框或密碼輸入框中一個字符都沒有被輸入的時候,禁用OK按鈕,使其不可被按下(當然,如果選擇作為游客訪問,那么OK 按總是處于啟用狀態)
  • Cancel按鈕總是處于啟用狀態,任何時候都可以按下該按鈕

類圖

在這里插入圖片描述

實現

中介者接口和組員接口的方法并非固定就是這些,當中介者和組員需要其他合作的話,就需要定義更多的方法

【中介者接口】

package com.atguigu.mediator.Sample;public interface Mediator {/*** 生成 Mediator 管理的組員*/public abstract void createColleagues();/*** 每個組員都會調用這個方法來向中介者匯報*/public abstract void colleagueChanged();
}

【組員接口】

package com.atguigu.mediator.Sample;public interface Colleague {/*** 設置中介者,告訴組員中介者是誰** @param mediator*/public abstract void setMediator(Mediator mediator);/*** 告知組員中介者所下達的指令* @param enabled 控制是否啟用組員的功能*/public abstract void setColleagueEnabled(boolean enabled);
}

【組員:按鈕】

package com.atguigu.mediator.Sample;import java.awt.*;public class ColleagueButton extends Button implements Colleague {private Mediator mediator;public ColleagueButton(String caption) {super(caption);}public void setMediator(Mediator mediator) {// 保存Mediatorthis.mediator = mediator;}public void setColleagueEnabled(boolean enabled) {// Mediator下達啟用/禁用的指示// setEnabled是java.awt.Button定義的方法,用來控制按鈕組件是啟用還是禁用,當設置為false時,按鈕無法被按下setEnabled(enabled);}
}

【組員:文本輸入框】

package com.atguigu.mediator.Sample;import java.awt.*;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;/*** 實現 TextListener 接口來實現監聽事件*/
public class ColleagueTextField extends TextField implements TextListener, Colleague {private Mediator mediator;public ColleagueTextField(String text, int columns) {   // 構造函數super(text, columns);}public void setMediator(Mediator mediator) {            // 保存Mediatorthis.mediator = mediator;}public void setColleagueEnabled(boolean enabled) {      // Mediator下達啟用/禁用的指示setEnabled(enabled);// 控件啟用時,背景色變成白色;否則變為灰色setBackground(enabled ? Color.white : Color.lightGray);}/*** TextListener 中定義的方法,監聽文本內容的變化,并通知中介者* @param e*/public void textValueChanged(TextEvent e) {// 當文字發生變化時通知Mediatormediator.colleagueChanged();}
}

【組員:單選按鈕】

package com.atguigu.mediator.Sample;import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;/*** 單選按鈕*/
public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {private Mediator mediator;public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) {// 構造函數super(caption, group, state);}public void setMediator(Mediator mediator) {// 保存Mediatorthis.mediator = mediator;}public void setColleagueEnabled(boolean enabled) {// Mediator下達啟用/禁用指示setEnabled(enabled);}/*** 監聽單選按鈕的狀態變化* @param e*/public void itemStateChanged(ItemEvent e) {// 當狀態發生變化時通知Mediatormediator.colleagueChanged();}
}

【具體中介者】

package com.atguigu.mediator.Sample;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;/*** 具體中介者*/
public class LoginFrame extends Frame implements ActionListener, Mediator {private ColleagueCheckbox checkGuest;private ColleagueCheckbox checkLogin;private ColleagueTextField textUser;private ColleagueTextField textPass;private ColleagueButton buttonOk;private ColleagueButton buttonCancel;/*** 構造函數* 生成并配置各個Colleague后,顯示對話框** @param title*/public LoginFrame(String title) {super(title);// 設置登錄對話框的背景顏色setBackground(Color.lightGray);// 使用布局管理器生成4×2窗格setLayout(new GridLayout(4, 2));// 生成各個 ColleaguecreateColleagues();// 配置 Colleagueadd(checkGuest);add(checkLogin);add(new Label("Username:"));add(textUser);add(new Label("Password:"));add(textPass);add(buttonOk);add(buttonCancel);// 設置初始的啟用起用/禁用狀態colleagueChanged();// 顯示pack();show();}/*** 生成登錄對話框所需要的各個Colleague*/public void createColleagues() {// 生成CheckboxGroup g = new CheckboxGroup();checkGuest = new ColleagueCheckbox("Guest", g, true);checkLogin = new ColleagueCheckbox("Login", g, false);textUser = new ColleagueTextField("", 10);textPass = new ColleagueTextField("", 10);textPass.setEchoChar('*');buttonOk = new ColleagueButton("OK");buttonCancel = new ColleagueButton("Cancel");// 設置MediatorcheckGuest.setMediator(this);checkLogin.setMediator(this);textUser.setMediator(this);textPass.setMediator(this);buttonOk.setMediator(this);buttonCancel.setMediator(this);// 設置ListenercheckGuest.addItemListener(checkGuest);checkLogin.addItemListener(checkLogin);textUser.addTextListener(textUser);textPass.addTextListener(textPass);buttonOk.addActionListener(this);buttonCancel.addActionListener(this);}/*** 控制各個成員的狀態* 接收來自于 Colleague 的通知,然后判斷各 Colleague 的啟用/禁用狀態* * 單選按鈕的選中狀態發生改變 或者 文本輸入框的內容發生改變,都會調用這個方法*/public void colleagueChanged() {// checkGuest.getState()獲取游客模式的按鈕是否處于選中狀態if (checkGuest.getState()) {// 游客模式textUser.setColleagueEnabled(false);textPass.setColleagueEnabled(false);buttonOk.setColleagueEnabled(true);} else {// 登錄模式textUser.setColleagueEnabled(true);userpassChanged();}}/*** 當textUser或是textPass文本輸入框中的文字發生變化時* 判斷各Colleage的啟用/禁用狀態*/private void userpassChanged() {if (textUser.getText().length() > 0) {textPass.setColleagueEnabled(true);if (textPass.getText().length() > 0) {buttonOk.setColleagueEnabled(true);} else {buttonOk.setColleagueEnabled(false);}} else {textPass.setColleagueEnabled(false);buttonOk.setColleagueEnabled(false);}}public void actionPerformed(ActionEvent e) {System.out.println(e.toString());System.exit(0);}
}

【主類】

package com.atguigu.mediator.Sample;public class Main {static public void main(String args[]) {new LoginFrame("Mediator Sample");}
}

【運行】

在這里插入圖片描述

總結

【優點】

  • 多個類相互耦合,會形成網狀結構(通信路線很多),使用中介者模式將網狀結構分離為星型結構進行解耦
  • 減少類間依賴,峰低了耦合,符合迪米特原則
  • 如果出現了Bug,比較容易定位Bug的位置
  • ConcreteColleague容易復用(如果需要寫一個新的對話框,那么按鈕、文本輸入框都可以很容易使用到新的對話框中)

【缺點】

  • 中介者承擔了較多的責任,一旦中介者出現了問題,整個系統就會受到影響
  • 如果設計不當,中介者對象本身變得過于復雜,這點在實際使用時,要特別注意
  • ConcreteMediator難以復用,因為其依賴于特定的應用程序

文章說明

  • 本文章為本人學習尚硅谷的學習筆記,文章中大部分內容來源于尚硅谷視頻(點擊學習尚硅谷相關課程),也有部分內容來自于自己的思考,發布文章是想幫助其他學習的人更方便地整理自己的筆記或者直接通過文章學習相關知識,如有侵權請聯系刪除,最后對尚硅谷的優質課程表示感謝。
  • 本人還同步閱讀《圖解設計模式》書籍(圖解設計模式/(日)結城浩著;楊文軒譯–北京:人民郵電出版社,2017.1),進而綜合兩者的內容,讓知識點更加全面

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

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

相關文章

css 實現 html 元素內文字水平垂直居中的N種方法

上一篇博文寫了div 中元素居中的N種常用方法&#xff0c;那么單個html元素&#xff1a;div&#xff08;塊級元素代表&#xff09;&#xff0c;span&#xff08;行內元素代表&#xff09;中的文字如何水平垂直都居中呢&#xff1f;實現方法如下&#xff1a; 本文例子使用的 html…

WebAPIs 第二天

DOM事件基礎 事件監聽事件類型事件對象 一.事件監聽 ① 概念&#xff1a;就是讓程序檢測是否有事件發生&#xff0c;一旦有事件觸發&#xff0c;就立即調用一個函數做出響應&#xff0c;也成為綁定事件或者注冊事件 ② 語法&#xff1a;元素對象.addEventListener(事件類型&…

機器學習---對數幾率回歸

1. 邏輯回歸 邏輯回歸&#xff08;Logistic Regression&#xff09;的模型是一個非線性模型&#xff0c; sigmoid函數&#xff0c;又稱邏輯回歸函數。但是它本質上又是一個線性回歸模型&#xff0c;因為除去sigmoid映射函 數關系&#xff0c;其他的步驟&#xff0c;算法都是…

從零開始,貪吃蛇小游戲系列專欄完美收官!

&#x1f3ae; 從零開始&#xff0c;貪吃蛇小游戲系列專欄完美收官&#xff01; &#x1f40d; 各位游戲開發探索者們&#xff0c;大家好&#xff01;我是[億元程序員]&#xff0c;一位擁有8年游戲開發經驗的主程。經過一段時間的努力&#xff0c;我很高興地宣布&#xff0c;我…

阿里云預裝LAMP應用導致MySQL不顯示訪問密碼如何解決

&#x1f600;前言 本篇博文是關于阿里云云服務器ECS部署MySQL過程中出現的一下坑&#xff0c;希望能夠幫助到您&#x1f60a; &#x1f3e0;個人主頁&#xff1a;晨犀主頁 &#x1f9d1;個人簡介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以幫助到大家…

SUB-1G SOC芯片DP4306F 32 位 ARM Cortex-M0+內核替代CMT2380F32

DP4306F是一款高性能低功耗的單片集成收發機&#xff0c;集成MO核MCU&#xff0c;工作頻率可覆蓋200MHiz^ 1000MHz。 支持230/408/433/470/868/915頻段。該芯片集成了射頻接收器、射頻發射器、頻率綜合器、GFSK調制器、GFSK解調器等功能模塊。通過SPI接口可以對輸出功率、頻道選…

gitlab-Runner搭建

root wget https://packages.gitlab.com/runner/gitlab-runner/packages/fedora/29/gitlab-runner-12.6.0-1.x86_64.rpm/download.rpm rpm -ivh download.rpm ---- 安裝 rpm -Uvh download.rpm -----更新升級 然后運行&#xff1a; gitlab-runner register --url https://git…

RabbitMQ相關面試題

用到了哪些MQ?什么使用場景?MQ的組成部分?MQ宕機了怎么辦?如何進行持久化的? MQ的選型? Kafka:高吞吐量、低延遲的分布式消息隊列,主要用于大規模數據處理和流式處理 RocketMQ:RocketMQ是阿里巴巴開源的分布式消息隊列,具有高吞吐量、低延遲、高可靠性等特點 RabbitM…

【Go 基礎篇】Go語言浮點類型:探索浮點數的特點與應用

介紹 浮點數是計算機編程中用于表示實數的一種數據類型&#xff0c;用于處理具有小數部分的數值。Go語言&#xff08;Golang&#xff09;提供了兩種主要的浮點數類型&#xff1a;float32和float64&#xff0c;分別用于單精度和雙精度浮點數的表示。本篇博客將深入探討Go語言中…

38 | 浦發銀行股票分析案例

本文將通過一個浦發銀行股票分析案例,探討如何從多個維度對股票進行分析,包括基本面、技術面和市場環境等因素。我們將深入挖掘浦發銀行的財務數據、業務模式以及市場定位,以了解其內在價值和潛在風險。同時,我們還將考察技術面的指標,如價格走勢、均線形態等,以揭示市場…

linux 命令--常用關機命令

1.使用shutdown命令 shutdown命令是Linux系統下最常用的關機命令之一。它可以讓系統在指定時間內進行關機或者重啟操作。例如&#xff0c;下面的命令可以讓系統在5分鐘后進行關機操作&#xff1a; sudo shutdown -h5其中&#xff0c;“-h”表示關機&#xff0c;“5”表示5分鐘…

ThinkPHP8命名規范-ThinkPHP8知識詳解

本文主要講解thinkphp8的命名規范&#xff0c;主要包括&#xff1a;遵循PHP自身的PSR-2命名規范和PSR-4自動加載規范、目錄和文件命名規范、函數和類、屬性命名規范、常量和配置命名規范、數據表和字段命名規范、不能使用PHP保留字。 在使用thinkphp8開發項目之前&#xff0c;…

C#使用OpenCv(OpenCVSharp)圖像全局二值化處理實例

本文實例演示C#語言中如何使用OpenCv(OpenCVSharp)對圖像進行全局二值化處理。 目錄 圖像二值化原理 函數原型 參數說明 實例 效果 圖像二值化原理

線程轉換狀態,傻傻分不清等待和阻塞嗎?你還在暴力的停止線程嗎?

線程切換 線程創建之后&#xff0c;調用start()方法開始運行。當線程執行wait()方法之后&#xff0c;線程進入等待狀態。進入等待狀態的線程需要依靠其他線程的通知才能夠返回到運行狀態&#xff0c;而超時等待狀態相當于在等待狀態的基礎上增加了超時限制&#xff0c;也就是超…

騰訊云服務器競價實例是什么?適用于什么行業?有啥優惠?

騰訊云服務器CVM計費模式分為包年包月、按量計費和競價實例&#xff0c;什么是競價實例&#xff1f;競價實例和按量付費相類似&#xff0c;優勢是價格更劃算&#xff0c;缺點是云服務器實例有被自動釋放風險&#xff0c;騰訊云服務器網來詳細說下什么是競價實例&#xff1f;以及…

GUI、多線程編程、網絡編程簡介

GUI、多線程編程、網絡編程簡介 文章目錄 GUI簡介什么是GUIGUI有什么用使用方法 多線程編程什么是多線程編程多線程編程有什么用提高程序的響應能力提高程序的性能實現異步編程并發數據訪問和共享資源實現復雜的算法和任務分解 進行多線程編程的步驟 網絡編程什么是網絡編程網絡…

JMeter處理接口簽名之BeanShell實現MD5加密

項目A需要給項目B提供一個接口&#xff0c;這個接口加密了&#xff0c;現在需要測試這個接口&#xff0c;需要怎么編寫腳本呢&#xff1f;實現接口簽名的方式有兩種&#xff1a;BeanShell實現MD5加密和函數助手實現MD5加密&#xff0c;之前已經分享過了函數助手實現MD5加密&…

React如何配置env環境變量

React版本&#xff1a; "react": "^18.2.0" 1、在package.json平級目錄下創建.env文件 2、在‘.env’文件里配置環境變量 【1】PUBLIC_URL 描述&#xff1a;編譯時文件的base-href 官方描述&#xff1a; // We use PUBLIC_URL environment variable …

從KM到Cure Models:常用生存分析方法的優缺點

一、引言 生存分析是一種用于研究個體生命長度或事件發生時間的統計方法。在許多領域中&#xff0c;如醫學、社會學、經濟學和工程學等&#xff0c;生存分析被廣泛應用于分析個體的生存時間&#xff0c;并研究相關因素對生存時間的影響。通過生存分析&#xff0c;我們可以評估特…

交換排序——選擇排序和冒泡排序的區別是什么?

今天重溫一下算法&#xff0c;其實剛開始我覺得冒泡排序和選擇排序是一樣的&#xff0c;因為他們排序過程中都是通過相鄰的數據比較找到最小/最大的數據&#xff0c;通過不斷思考和學習才明白&#xff0c;兩者還是有區別的。 冒泡排序 概念 冒泡排序(Bubble Sort)&#xff0…