2024050402-重學 Java 設計模式《實戰責任鏈模式》

重學 Java 設計模式:實戰責任鏈模式「模擬618電商大促期間,項目上線流程多級負責人審批場景」

一、前言

場地和場景的重要性

射擊🏹需要去靶場學習、滑雪🏂需要去雪場體驗、開車🚗需要能上路實踐,而編程開發除了能完成產品的功能流程,還需要保證系統的可靠性能。就像你能聽到的一些系統監控指標;QPSTPSTP99TP999可用率響應時長等等,而這些指標的總和評估就是一個系統的健康度。但如果你幾乎沒有聽到這樣的技術術語,也沒接觸過類似高并發場景,那么就很像駕駛證的科目1考了100分,但不能上路。沒有這樣的技術場景給你訓練,讓你不斷的體會系統的脾氣秉性,即便你有再多的想法都沒法實現。所以,如果真的想學習一定要去一個有實操的場景,下水試試才能學會狗刨。

你的視覺盲區有多大

同樣一本書、同樣一條路、同樣一座城,你真的以為生活有選擇嗎?有時候很多選項都是擺設,給你多少次機會你都選的一模一樣。這不是你選不選而是你的認知范圍決定了你下一秒做的事情,另外的一個下一秒又決定了再下一個下一秒。就像管中窺豹一樣,20%的面積在你視覺里都是黑色的,甚至就總是忽略看不到,而這看不到的20%就是生命中的時運!但,人可以學習,可以成長,可以脫胎換骨,可以努力付出,通過一次次的蛻變而看到剩下的20%!

沒有設計圖紙你敢蓋樓嗎

編程開發中最好的什么,是設計。運用架構思維、經驗心得、才華靈感,構建出最佳的系統。真正的研發會把自己寫的代碼當做作品來欣賞,你說這是一份工作,但在這樣的人眼里這可不是一份工作,而是一份工匠精神。就像可能時而你也會為自己因為一個niubility的設計而豪邁萬丈,為能上線一個扛得住每秒200萬訪問量的系統會精神煥發。這樣的自豪感就是一次次壘磚一樣墊高腳底,不斷的把你的視野提高,讓你能看到上層設計也能知曉根基建設。可以把控全局,也可以治理細節。這一份份知識的沉淀,來幫助你繪制出一張系統架構藍圖。

二、開發環境

  1. JDK 1.8
  2. Idea + Maven
  3. 涉及工程三個,可以通過關注公眾號bugstack蟲洞棧,回復源碼下載獲取(打開獲取的鏈接,找到序號18)
工程描述
itstack-demo-design-13-00場景模擬工程;模擬一個上線流程審批的接口。
itstack-demo-design-13-01使用一坨代碼實現業務需求
itstack-demo-design-13-02通過設計模式優化改造代碼,產生對比性從而學習

三、責任鏈模式介紹

責任鏈模式,圖片來自 refactoringguru.cn

  • 圖片來自:https://refactoringguru.cn/design-patterns/chain-of-responsibility

擊鼓傳雷,看上圖你是否想起周星馳有一個電影,大家坐在海邊圍成一個圈,拿著一個點燃的炸彈,互相傳遞。

責任鏈模式的核心是解決一組服務中的先后執行處理關系,就有點像你沒錢花了,需要家庭財務支出審批,10塊錢以下找閨女審批,100塊錢先閨女審批在媳婦審批。你可以理解想象成當你要跳槽的時候被安排的明明白白的被各個領導簽字放行。

四、案例場景模擬

場景模擬;618大促場景上線審批場景

在本案例中我們模擬在618大促期間的業務系統上線審批流程場景

像是這些一線電商類的互聯網公司,阿里、京東、拼多多等,在618期間都會做一些運營活動場景以及提供的擴容備戰,就像過年期間百度的紅包一樣。但是所有開發的這些系統都需要陸續的上線,因為臨近618有時候也有一些緊急的調整的需要上線,但為了保障線上系統的穩定性是盡可能的減少上線的,也會相應的增強審批力度。就像一級響應、二級響應一樣。

而這審批的過程在隨著特定時間點會增加不同級別的負責人加入,每個人就像責任鏈模式中的每一個核心點。對于研發小伙伴并不需要關心具體的審批流程處理細節,只需要知道這個上線更嚴格,級別也更高,但對于研發人員來說同樣是點擊相同的提審按鈕,等待審核。

接下來我們就模擬這樣一個業務訴求場景,使用責任鏈的設計模式來實現此功能。

1. 場景模擬工程

itstack-demo-design-13-00
└── src└── main└── java└── org.itstack.demo.design└── AuthService.java
  • 這里的代碼結構比較簡單,只有一個模擬審核和查詢審核結果的服務類。相當于你可以調用這個類去審核工程和獲取審核結構,這部分結果信息是模擬的寫到緩存實現。

2. 場景簡述

2.1 模擬審核服務
public class AuthService {private static Map<String, Date> authMap = new ConcurrentHashMap<String, Date>();public static Date queryAuthInfo(String uId, String orderId) {return authMap.get(uId.concat(orderId));}public static void auth(String uId, String orderId) {authMap.put(uId.concat(orderId), new Date());}}
  • 這里面提供了兩個接口一個是查詢審核結果(queryAuthInfo)、另外一個是處理審核(auth)。
  • 這部分是把由誰審核的和審核的單子ID作為唯一key值記錄到內存Map結構中。

五、用一坨坨代碼實現

這里我們先使用最直接的方式來實現功能

按照我們的需求審批流程,平常系統上線只需要三級負責人審批就可以,但是到了618大促時間點,就需要由二級負責以及一級負責人一起加入審批系統上線流程。在這里我們使用非常直接的if判斷方式來實現這樣的需求。

1. 工程結構

itstack-demo-design-13-01
└── src└── main└── java└── org.itstack.demo.design└── AuthController.java
  • 這部分非常簡單的只包含了一個審核的控制類,就像有些伙伴開始寫代碼一樣,一個類寫所有需求。

2. 代碼實現

public class AuthController {private SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 時間格式化public AuthInfo doAuth(String uId, String orderId, Date authDate) throws ParseException {// 三級審批Date date = AuthService.queryAuthInfo("1000013", orderId);if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態:待三級審批負責人 ", "王工");// 二級審批if (authDate.after(f.parse("2020-06-01 00:00:00")) && authDate.before(f.parse("2020-06-25 23:59:59"))) {date = AuthService.queryAuthInfo("1000012", orderId);if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態:待二級審批負責人 ", "張經理");}// 一級審批if (authDate.after(f.parse("2020-06-11 00:00:00")) && authDate.before(f.parse("2020-06-20 23:59:59"))) {date = AuthService.queryAuthInfo("1000011", orderId);if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態:待一級審批負責人 ", "段總");}return new AuthInfo("0001", "單號:", orderId, " 狀態:審批完成");}}
  • 這里從上到下分別判斷了在指定時間范圍內由不同的人員進行審批,就像618上線的時候需要三個負責人都審批才能讓系統進行上線。
  • 像是這樣的功能看起來很簡單的,但是實際的業務中會有很多部門,但如果這樣實現就很難進行擴展,并且在改動擴展調整也非常麻煩。

3. 測試驗證

3.1 編寫測試類
@Test
public void test_AuthController() throws ParseException {AuthController authController = new AuthController();  // 模擬三級負責人審批logger.info("測試結果:{}", JSON.toJSONString(authController.doAuth("小傅哥", "1000998004813441", new Date())));logger.info("測試結果:{}", "模擬三級負責人審批,王工");AuthService.auth("1000013", "1000998004813441");  // 模擬二級負責人審批                                 logger.info("測試結果:{}", JSON.toJSONString(authController.doAuth("小傅哥", "1000998004813441", new Date())));logger.info("測試結果:{}", "模擬二級負責人審批,張經理");AuthService.auth("1000012", "1000998004813441");    // 模擬一級負責人審批logger.info("測試結果:{}", JSON.toJSONString(authController.doAuth("小傅哥", "1000998004813441", new Date())));logger.info("測試結果:{}", "模擬一級負責人審批,段總");AuthService.auth("1000011", "1000998004813441");            logger.info("測試結果:{}", "審批完成");
}
  • 這里模擬每次查詢是否審批完成,隨著審批的不同節點,之后繼續由不同的負責人進行審批操作。
  • authController.doAuth,是查看審批的流程節點、AuthService.auth,是審批方法用于操作節點流程狀態。
3.2 測試結果
23:25:00.363 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待三級審批負責人 王工"}
23:25:00.366 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬三級負責人審批,王工
23:25:00.367 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待二級審批負責人 張經理"}
23:25:00.367 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬二級負責人審批,張經理
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待一級審批負責人 段總"}
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬一級負責人審批,段總
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:審批完成Process finished with exit code 0
  • 從測試結果上可以看到一層層的由不同的人員進行審批,審批完成后到下一個人進行處理。單看結果是滿足我們的訴求,只不過很難擴展和調整流程,相當于代碼寫的死死的。

六、責任鏈模式重構代碼

接下來使用裝飾器模式來進行代碼優化,也算是一次很小的重構。

責任鏈模式可以讓各個服務模塊更加清晰,而每一個模塊間可以通過next的方式進行獲取。而每一個next是由繼承的統一抽象類實現的。最終所有類的職責可以動態的進行編排使用,編排的過程可以做成可配置化。

1. 工程結構

itstack-demo-design-13-02
└── src└── main└── java└── org.itstack.demo.design├── impl│    ├── Level1AuthLink.java│    ├── Level2AuthLink.java│    └── Level3AuthLink.java├── AuthInfo.java└── AuthLink.java

責任鏈類圖

責任鏈類圖

責任鏈模式模型結構

責任鏈模式模型結構

  • 上圖是這個業務模型中責任鏈結構的核心部分,通過三個實現了統一抽象類AuthLink的不同規則,再進行責任編排模擬出一條鏈路。這個鏈路就是業務中的責任鏈。
  • 一般在使用責任鏈時候如果是場景比較固定,可以通過寫死到代碼中進行初始化。但如果業務場景經常變化可以做成xml配置的方式進行處理,也可以落到庫里進行初始化操作。

2. 代碼實現

2.1 責任鏈中返回對象定義
public class AuthInfo {private String code;private String info = "";public AuthInfo(String code, String ...infos) {this.code = code;for (String str:infos){this.info = this.info.concat(str);}}// ...get/set
}
  • 這個類的是包裝了責任鏈處理過程中返回結果的類,方面處理每個責任鏈的返回信息。
2.2 鏈路抽象類定義
public abstract class AuthLink {protected Logger logger = LoggerFactory.getLogger(AuthLink.class);protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 時間格式化protected String levelUserId;                           // 級別人員IDprotected String levelUserName;                         // 級別人員姓名private AuthLink next;                                  // 責任鏈public AuthLink(String levelUserId, String levelUserName) {this.levelUserId = levelUserId;this.levelUserName = levelUserName;}public AuthLink next() {return next;}public AuthLink appendNext(AuthLink next) {this.next = next;return this;}public abstract AuthInfo doAuth(String uId, String orderId, Date authDate);}
  • 這部分是責任鏈,鏈接起來的核心部分。AuthLink next,重點在于可以通過next方式獲取下一個鏈路需要處理的節點。
  • levelUserIdlevelUserName,是責任鏈中的公用信息,標記每一個審核節點的人員信息。
  • 抽象類中定義了一個抽象方法,abstract AuthInfo doAuth,這是每一個實現者必須實現的類,不同的審核級別處理不同的業務。
2.3 三個審核實現類

Level1AuthLink

public class Level1AuthLink extends AuthLink {public Level1AuthLink(String levelUserId, String levelUserName) {super(levelUserId, levelUserName);}public AuthInfo doAuth(String uId, String orderId, Date authDate) {Date date = AuthService.queryAuthInfo(levelUserId, orderId);if (null == date) {return new AuthInfo("0001", "單號:", orderId, " 狀態:待一級審批負責人 ", levelUserName);}AuthLink next = super.next();if (null == next) {return new AuthInfo("0000", "單號:", orderId, " 狀態:一級審批完成負責人", " 時間:", f.format(date), " 審批人:", levelUserName);}return next.doAuth(uId, orderId, authDate);}}

Level2AuthLink

public class Level2AuthLink extends AuthLink {private Date beginDate = f.parse("2020-06-11 00:00:00");private Date endDate = f.parse("2020-06-20 23:59:59");public Level2AuthLink(String levelUserId, String levelUserName) throws ParseException {super(levelUserId, levelUserName);}public AuthInfo doAuth(String uId, String orderId, Date authDate) {Date date = AuthService.queryAuthInfo(levelUserId, orderId);if (null == date) {return new AuthInfo("0001", "單號:", orderId, " 狀態:待二級審批負責人 ", levelUserName);}AuthLink next = super.next();if (null == next) {return new AuthInfo("0000", "單號:", orderId, " 狀態:二級審批完成負責人", " 時間:", f.format(date), " 審批人:", levelUserName);}if (authDate.before(beginDate) || authDate.after(endDate)) {return new AuthInfo("0000", "單號:", orderId, " 狀態:二級審批完成負責人", " 時間:", f.format(date), " 審批人:", levelUserName);}return next.doAuth(uId, orderId, authDate);}}

Level3AuthLink

public class Level3AuthLink extends AuthLink {private Date beginDate = f.parse("2020-06-01 00:00:00");private Date endDate = f.parse("2020-06-25 23:59:59");public Level3AuthLink(String levelUserId, String levelUserName) throws ParseException {super(levelUserId, levelUserName);}public AuthInfo doAuth(String uId, String orderId, Date authDate) {Date date = AuthService.queryAuthInfo(levelUserId, orderId);if (null == date) {return new AuthInfo("0001", "單號:", orderId, " 狀態:待三級審批負責人 ", levelUserName);}AuthLink next = super.next();if (null == next) {return new AuthInfo("0000", "單號:", orderId, " 狀態:三級審批負責人完成", " 時間:", f.format(date), " 審批人:", levelUserName);}if (authDate.before(beginDate) || authDate.after(endDate)) {return new AuthInfo("0000", "單號:", orderId, " 狀態:三級審批負責人完成", " 時間:", f.format(date), " 審批人:", levelUserName);}return next.doAuth(uId, orderId, authDate);}}
  • 如上三個類;Level1AuthLinkLevel2AuthLinkLevel3AuthLink,實現了不同的審核級別處理的簡單邏輯。
  • 例如第一個審核類中會先判斷是否審核通過,如果沒有審核通過則返回結果給調用方,引導去審核。(這里簡單模擬審核后有時間信息不為空,作為判斷條件)
  • 判斷完成后獲取下一個審核節點;super.next();,如果不存在下一個節點,則直接返回結果。
  • 之后是根據不同的業務時間段進行判斷是否需要,二級和一級的審核。
  • 最后返回下一個審核結果;next.doAuth(uId, orderId, authDate);,有點像遞歸調用。

3. 測試驗證

3.1 編寫測試類
@Test
public void test_AuthLink() throws ParseException {AuthLink authLink = new Level3AuthLink("1000013", "王工").appendNext(new Level2AuthLink("1000012", "張經理").appendNext(new Level1AuthLink("1000011", "段總")));logger.info("測試結果:{}", JSON.toJSONString(authLink.doAuth("小傅哥", "1000998004813441", new Date())));// 模擬三級負責人審批AuthService.auth("1000013", "1000998004813441");logger.info("測試結果:{}", "模擬三級負責人審批,王工");logger.info("測試結果:{}", JSON.toJSONString(authLink.doAuth("小傅哥", "1000998004813441", new Date())));// 模擬二級負責人審批AuthService.auth("1000012", "1000998004813441");logger.info("測試結果:{}", "模擬二級負責人審批,張經理");logger.info("測試結果:{}", JSON.toJSONString(authLink.doAuth("小傅哥", "1000998004813441", new Date())));// 模擬一級負責人審批AuthService.auth("1000011", "1000998004813441");logger.info("測試結果:{}", "模擬一級負責人審批,段總");logger.info("測試結果:{}", JSON.toJSONString(authLink.doAuth("小傅哥", "1000998004813441", new Date())));
}
  • 這里包括最核心的責任鏈創建,實際的業務中會包裝到控制層; AuthLink authLink = new Level3AuthLink("1000013", "王工") .appendNext(new Level2AuthLink("1000012", "張經理") .appendNext(new Level1AuthLink("1000011", "段總"))); 通過把不同的責任節點進行組裝,構成一條完整業務的責任鏈。
  • 接下里不斷的執行查看審核鏈路authLink.doAuth(...),通過返回結果對數據進行3、2、1級負責人審核,直至最后審核全部完成。
3.2 測試結果
23:49:46.585 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待三級審批負責人 王工"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬三級負責人審批,王工
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待二級審批負責人 張經理"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬二級負責人審批,張經理
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0001","info":"單號:1000998004813441 狀態:待一級審批負責人 段總"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:模擬一級負責人審批,段總
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結果:{"code":"0000","info":"單號:1000998004813441 狀態:一級審批完成負責人 時間:2020-06-18 23:49:46 審批人:段總"}Process finished with exit code 0
  • 從上述的結果可以看到我們的責任鏈已經生效,按照責任鏈的結構一層層審批,直至最后輸出審批結束到一級完成的結果。
  • 這樣責任鏈的設計方式可以方便的進行擴展和維護,也把if語句干掉了。

七、總結

  • 從上面代碼從if語句重構到使用責任鏈模式開發可以看到,我們的代碼結構變得清晰干凈了,也解決了大量if語句的使用。并不是if語句不好,只不過if語句并不適合做系統流程設計,但是在做判斷和行為邏輯處理中還是非常可以使用的。
  • 在我們前面學習結構性模式中講到過組合模式,它像是一顆組合樹一樣,我們搭建出一個流程決策樹。其實這樣的模式也是可以和責任鏈模型進行組合擴展使用,而這部分的重點在于如何關聯鏈路的關聯,最終的執行都是在執行在中間的關系鏈。
  • 責任鏈模式很好的處理單一職責和開閉原則,簡單了耦合也使對象關系更加清晰,而且外部的調用方并不需要關心責任鏈是如何進行處理的*(以上程序中可以把責任鏈的組合進行包裝,在提供給外部使用)*。但除了這些優點外也需要是適當的場景才進行使用,避免造成性能以及編排混亂調試測試疏漏問題。

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

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

相關文章

Scanpy(4)用與數據整合和批次處理

Scanpy包,用與數據整合和批次處理,包含批次效應的BBKNN算法和用于對比的ingest基礎算法比較,及其原理簡介。 1. 依賴: (1)數據集(全部需要掛VPN): PBMC:pbmc3k_processed()(需要下載);pbmc68k_reduced()(scanpy自帶)Pancreas(需要下載)(2)Python包:Scanp…

【Python】把xmind轉換為指定格式txt文本

人工智能訓練通常需要使用文本格式&#xff0c;xmind作為一種常規格式不好進行解析&#xff0c;那如何把xmind轉換為txt格式呢&#xff1f; 軟件信息 python python -v Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32…

Python 包安裝及常用命令【python 入門】

背景&#xff1a; 近期看到一個項目&#xff0c;做微信只能機器人&#xff0c;服務是使用python搭建的&#xff0c;于是拷貝下來自己打算跑一跑&#xff0c;部署一下&#xff0c;可是自己又沒有python的經驗&#xff0c;于是各種查資料學習&#xff0c;跟著敲一敲&#xff0c;順…

Go 1.19.4 切片與子切片-Day 05

1. 切片 1.1 介紹 切片在Go中是一個引用類型&#xff0c;它包含三個組成部分&#xff1a;指向底層數組的指針&#xff08;pointer&#xff09;、切片的長度&#xff08;length&#xff09;以及切片的容量&#xff08;capacity&#xff09;&#xff0c;這些信息共同構成了切片的…

單片機排水泵高壓方案

靈動微多顆算力高、高可靠性的通用系列和電機專用系列MCU&#xff0c;配合成熟的控制算法&#xff0c;覆蓋了包括洗衣機在內的各種大小家電市場。 RAMSUN提供的MM32 MCU種類較多&#xff0c;例如洗衣機內部的排水泵系統&#xff0c;排水泵控制首選電控高性價比產品MM32SPIN023…

JavaWeb_SpringBootWeb案例

環境搭建&#xff1a; 開發規范 接口風格-Restful&#xff1a; 統一響應結果-Result&#xff1a; 開發流程&#xff1a; 第一步應該根據需求定義表結構和定義接口文檔 注意&#xff1a; 本文代碼從上往下一直添加功能&#xff0c;后面的模塊下的代碼包括前面的模塊&#xff0c…

Xmind Pro 2024 專業版激活碼(附下載鏈接)

說到思維導圖&#xff0c;就不能不提 Xmind。這是一款優秀的思維導圖工具&#xff0c;擁有著豐富的導圖模板&#xff0c;漂亮的界面和配色&#xff0c;以及各種各樣的創意工具。 新架構速度更快 采用全新 Snowdancer 引擎&#xff0c;一種堪稱「黑科技」的先進圖形渲染技術。…

翹首以盼的抗鋸齒

Antialiasing 實際的圖形學中是怎么實現反走樣的呢&#xff1f; 我們不希望實際產出的圖形有鋸齒效果&#xff0c;那怎么辦呢&#xff1f; 從采樣的理論開始談起吧 Simpling theory 照片也是一種采樣&#xff0c;把景象打散成像素放到屏幕上的過程&#xff1a; 還可以在不…

14、企業數據資源相關會計處理暫行規定

為規范企業數據資源相關會計處理, 強化相關會計信息披露, 根據《中華人民共和國會計法》 和企業會計準則等相關規定, 現對企業數據資源的相關會計處理規定如下: 一、 關于適用范圍 本規定適用于企業按照企業會計準則相關規定確認為無形資產或存貨等資產類別的數據資源,以…

21 - 即時食物配送 II(高頻 SQL 50 題基礎版)

21 - 即時食物配送 II -- sum(if(order_datecustomer_pref_delivery_date,1,0))/count(*)sum(order_datecustomer_pref_delivery_date)/count(*) -- count(*),表示數據的行數&#xff0c;如果有分組&#xff0c;為分組后數據的行數select round(100*sum(if(order_datecustomer_…

【名詞解釋】Unity的Button組件及其使用示例

Unity的Button組件是Unity引擎中UI系統的一部分&#xff0c;它允許用戶創建可交互的按鈕&#xff0c;用戶可以點擊這些按鈕來觸發事件。Button組件通常用于游戲界面中&#xff0c;比如開始游戲、暫停游戲、選擇選項等。 Button組件的主要屬性包括&#xff1a; interactable: …

原來Stable Diffusion是這樣工作的

stable diffusion是一種潛在擴散模型&#xff0c;可以從文本生成人工智能圖像。為什么叫做潛在擴散模型呢&#xff1f;這是因為與在高維圖像空間中操作不同&#xff0c;它首先將圖像壓縮到潛在空間中&#xff0c;然后再進行操作。 在這篇文章中&#xff0c;我們將深入了解它到…

達摩院重大“遺產”!fluxonium量子比特初始化300納秒且保真度超過99%

通用量子計算機開發的主要挑戰之一是制備量子比特。十多年來&#xff0c;研究人員在構建量子計算機的過程中主要使用了transmon量子比特&#xff0c;這也是迄今為止商業上最成功的超導量子比特。 但與業界多數選擇transmon量子比特不同&#xff0c;&#xff08;前&#xff09;…

npm運行報錯:無法加載文件 C:\Program Files\nodejs\npm.ps1,因為在此系統上禁止運行腳本問題解決

問題其實已經顯而易見了 系統禁止運行腳本 以管理員身份運行 PowerShell&#xff1a; 右鍵點擊“開始”按鈕或按 Win X&#xff0c;然后選擇“Windows PowerShell(管理員)”。 查看當前執行策略&#xff1a; 在 PowerShell 中輸入以下命令來查看當前的執行策略&#xff1a; G…

Python文本處理利器:jieba庫全解析

文章目錄 Python文本處理利器&#xff1a;jieba庫全解析第一部分&#xff1a;背景和功能介紹第二部分&#xff1a;庫的概述第三部分&#xff1a;安裝方法第四部分&#xff1a;常用庫函數介紹1. 精確模式分詞2. 全模式分詞3. 搜索引擎模式分詞4. 添加自定義詞典5. 關鍵詞提取 第…

服務器遭遇UDP攻擊時的應對與解決方案

UDP攻擊作為分布式拒絕服務(DDoS)攻擊的一種常見形式&#xff0c;通過發送大量的UDP數據包淹沒目標服務器&#xff0c;導致網絡擁塞、服務中斷。本文旨在提供一套實用的策略與技術手段&#xff0c;幫助您識別、緩解乃至防御UDP攻擊&#xff0c;確保服務器穩定運行。我們將探討監…

最新PHP眾籌網站源碼 支持報名眾籌+商品眾籌+公益眾籌等多種眾籌模式 含完整代碼包和部署教程

在當今互聯網飛速發展的時代&#xff0c;眾籌模式逐漸成為了創新項目、商品銷售和公益活動融資的重要渠道。分享一款最新版的PHP眾籌網站源碼&#xff0c;支持報名眾籌、商品眾籌和公益眾籌等多種眾籌模式。該源碼包含了完整的代碼包和詳細的部署教程&#xff0c;讓新手也可以輕…

利用醫學Twitter進行病理圖像分析的視覺-語言基礎模型| 文獻速遞-視覺通用模型與疾病診斷

Title 題目 A visual–language foundation model for pathology image analysis using medical Twitter 利用醫學Twitter進行病理圖像分析的視覺-語言基礎模型 01 文獻速遞介紹 缺乏公開可用的醫學圖像標注是計算研究和教育創新的一個重要障礙。同時&#xff0c;許多醫生…

自動化測試-Selenium(一),簡介

自動化測試-Selenium 1. 什么是自動化測試 1.1 自動化測試介紹 自動化測試是一種通過自動化工具執行測試用例來驗證軟件功能和性能的過程。與手動測試不同&#xff0c;自動化測試使用腳本和軟件來自動執行測試步驟&#xff0c;記錄結果&#xff0c;并比較預期輸出和實際輸出…

【Python報錯】已解決ModuleNotFoundError: No module named ‘timm’

成功解決“ModuleNotFoundError: No module named ‘timm’”錯誤的全面指南 一、引言 在Python編程中&#xff0c;經常會遇到各種導入模塊的錯誤&#xff0c;其中“ModuleNotFoundError: No module named ‘timm’”就是一個典型的例子。這個錯誤意味著你的Python環境中沒有安…