設計模式 四、行為設計模式(2)

五、狀態模式

? ? ? ? 1、概述

? ? ? ? ?狀態設計模式是一種行為型設計模式,它允許對象在其內部狀態發生時改變其行為,這種模式可以消除大量的條件語句,并將每個狀態的行為封裝到單獨的類中。

? ? ? ? 狀態模式的主要組成部分如下:
? ? ? ? 1)上下文(Context):上下文通常包含一個具體狀態的引用,用于維護當前狀態,上下文委托給當前對象處理狀態相關行為。
? ? ? ? 2)抽象狀態(State):定義一個接口,用于封裝與上下文的特定狀態相關的行為。
? ? ? ? 3)具體狀態(Concrete State):實現抽象狀態接口,為具體狀態定義行為。每個具體狀態類對應一個狀態。

? ? ? ? 簡單示例,假設要模擬一個簡易的電視遙控器,具有開啟、關閉和調整音量的功能。
? ? ? ? 假設不使用設計模式:

public class TV {private boolean isOn;private int volume;public TV() {isOn = false;volume = 0;}public void turnOn() {// 如果是開啟狀態if (isOn) {System.out.println("TV is already on.");// 否則打開電視} else {isOn = true;System.out.println("Turning on the TV.");}}public void turnOff() {if (isOn) {isOn = false;System.out.println("Turning off the TV.");} else {System.out.println("TV is already off.");}}public void adjustVolume(int volume) {if (isOn) {this.volume = volume;System.out.println("Adjusting volume to: " + volume);} else {System.out.println("Cannot adjust volume, TV is off.");}}
}
public class Main {public static void main(String[] args) {TV tv = new TV();tv.turnOn();tv.adjustVolume(10);tv.turnOff();}
}

? ? ? ? 該例子中我們狀態比較少,所以代碼看起來也不是很復雜,但是狀態如果變多了就會變得不好控制,比如增加換臺,快捷鍵,靜音等功能。
????????使用狀態設計模式之后:
? ? ? ? 首先定義抽象狀態接口TVState,將每一個修改狀態的動作抽象成一個接口:

public interface TVState {void turnOn();void turnOff();void adjustVolume(int volume);
}

? ? ? ? 接下來為每個具體的狀態創建類,實現TVState接口,例如:創建TVOnState 和 TVOffState 類:

// 在on狀態下,去執行以下各種操作
public class TVOnState implements TVState {@Overridepublic void turnOn() {System.out.println("TV is already on.");}@Overridepublic void turnOff() {System.out.println("Turning off the TV.");}@Overridepublic void adjustVolume(int volume) {System.out.println("Adjusting volume to: " + volume);}
}
// 在關機的狀態下執行以下的操作
public class TVOffState implements TVState {@Overridepublic void turnOn() {System.out.println("Turning on the TV.");}@Overridepublic void turnOff() {System.out.println("TV is already off.");}@Overridepublic void adjustVolume(int volume) {System.out.println("Cannot adjust volume, TV is off.");}
}

? ? ? ? 接下來定義上下文類TV:

public class TV {// 當前狀態private TVState state;public TV() {state = new TVOffState();}public void setState(TVState state) {this.state = state;}public void turnOn() {// 打開state.turnOn();// 設置為開機狀態setState(new TVOnState());}public void turnOff() {// 關閉state.turnOff();// 設置為關機狀態setState(new TVOffState());}public void adjustVolume(int volume) {state.adjustVolume(volume);}
}

? ? ? ? 最后通過以下方式使用這些類:

public class Main {public static void main(String[] args) {TV tv = new TV();tv.turnOn();tv.adjustVolume(10);tv.turnOff();}
}

????????這個例子展示了狀態模式的基本結構和用法。通過使用狀態模式,我們可以更好地組織和管理與特定狀態相關的代碼。當狀態較多時,這種模式的優勢就會凸顯出來,同時我們在代碼時,因為我們會對每個狀態進行獨立封裝,所以也會簡化代碼編寫。

? ? ? ? 2、有限狀態機

? ? ? ? 有限狀態機,英文翻譯時Flinite State Machine,縮寫為FSM,簡稱狀態機,比較官方的說法是:有限狀態機是描述對象在它的生命周期內所經歷的狀態序列,以及如何響應來自外界的各種事件。狀態機有3個組成部分:狀態(State)、事件(Event)、動作(Action)。其中,事件也成為轉移條件(Transition Condition)。事件觸發狀態的轉移及動作的執行,不過,動作不是必須的,也可能只轉移狀態,不執行任何動作。

? ? ? ? 2.1 分支法

? ? ? ? 如何實現狀態機,總結了三種方式。其中,最簡單直接的實現方式是,參照狀態轉移圖,將每一個狀態轉移。原模原樣的直譯成代碼。這樣編寫的代碼會包含大量的 if - else或 switch-case 分支判斷邏輯,甚至是嵌套的分支判斷邏輯。所以我們把這種方法暫且命名為分支法:

? ??????下面是一個使用if-else 語句實現的馬里奧形態變化的代碼示例:

public class Mario {private MarioState state;public Mario() {state = MarioState.SMALL;}public void handleEvent(Event event) {MarioState newState = state;// 處理吃蘑菇事件if (event == Event.MUSHROOM) {if (state == MarioState.SMALL) {newState = MarioState.BIG;}// 處理吃火花事件} else if (event == Event.FIRE_FLOWER) {if (state == MarioState.BIG) {newState = MarioState.FIRE;}// 處理遇到小怪事件} else if (event == Event.ENEMY_ATTACK) {if (state == MarioState.BIG) {newState = MarioState.SMALL;} else if (state == MarioState.FIRE) {newState = MarioState.BIG;} else if (state == MarioState.SMALL) {newState = MarioState.DEAD;}// 處理掉坑事件} else if (event == Event.FALL_INTO_PIT) {newState = MarioState.DEAD;}System.out.printf("從 %s 變為 %s%n", state, newState);state = newState;}
}
public class MarioDemo {public static void main(String[] args) {Mario mario = new Mario();mario.handleEvent(Event.MUSHROOM); // 變為大馬里奧mario.handleEvent(Event.FIRE_FLOWER); // 變為火焰馬里奧mario.handleEvent(Event.ENEMY_ATTACK); // 變為死亡馬里奧}
}
????????在這個示例中,我們使用 if-else 語句來處理狀態轉換。 handleEvent 方法中,我們根據事件和當前狀態的組合來確定新狀態 ,并 更新馬里奧的狀態 。這種實現方法相較于查表法和面向對象實現更為簡單,但可能在狀態和事件更多的情況下變得難以維護。選擇合適的實現方法取決于實際需求和場景。

? ? ? ? 2.2 查表法

? ? ? ? ? ?該種方法略,不怎么用,可以自己查資料。

? ? ? ? 2.3 狀態模式

? ? ? ??在查表法的代碼實現中,事件觸發的動作只是簡單的狀態或者數值,所以,我們用一個 MarioState類型的二維數組 TRANSITION_TABLE 就能表示,二維數組中的值表示出發事件后的新狀態。但是,如果要執行的動作并非這么簡單,而是一系列復雜的邏輯操作(比如加減分數、處理位置信息等等),我們就沒法用如此簡單的二維數組來表示了。這也就是說,查表法的實現方式有一定局限性

????????雖然分支邏輯的實現方式不存在這個問題,但它又存在前面講到的其他問題,比如分支判斷邏輯較多,導致代碼可讀性和可維護性不好等。實際上,針對分支邏輯法存在的問題,我們可以使用狀態模式來解決

????????狀態模式通過將事件觸發的狀態轉移和動作執行,拆分到不同的狀態類中,來避免分支判斷邏輯。我們還是結合代碼來理解這句話。利用狀態模式,我們來補全 MarioStateMachine 類,補全后的代碼如下所示。

????????以下是一個使用 Java 實現的簡化版馬里奧形態變化的案例代碼,我為代碼添加了中文注釋以便理解:

// 定義事件枚舉類型
enum Event {// 吃蘑菇,吃火花,遇到小怪,調入深坑MUSHROOM, FIRE_FLOWER, ENEMY_ATTACK, FALL_INTO_PIT
}
// 定義馬里奧狀態接口
interface MarioState {void handleEvent(Event event);
}
// 實現死亡馬里奧狀態
class DeadMario implements MarioState {private Mario mario;public DeadMario(Mario mario) {this.mario = mario;}@Overridepublic void handleEvent(Event event) {System.out.println("馬里奧已死亡,無法處理事件");}
}
// 實現小馬里奧狀態
class SmallMario implements MarioState {private Mario mario;public SmallMario(Mario mario) {this.mario = mario;}@Overridepublic void handleEvent(Event event) {switch (event) {case MUSHROOM:System.out.println("變為大馬里奧");mario.setState(new BigMario(mario));break;case FIRE_FLOWER:System.out.println("小馬里奧不能直接變為火焰馬里奧");break;case ENEMY_ATTACK:System.out.println("小瑪麗奧去世了");mario.setState(new DeadMario(mario));break;case FALL_INTO_PIT:System.out.println("小瑪麗奧去世了");mario.setState(new DeadMario(mario));break;}}
}
// 實現大馬里奧狀態
class BigMario implements MarioState {private Mario mario;public BigMario(Mario mario) {this.mario = mario;}@Overridepublic void handleEvent(Event event) {switch (event) {case MUSHROOM:System.out.println("保持大馬里奧");break;case FIRE_FLOWER:System.out.println("變為火焰馬里奧");mario.setState(new FireMario(mario));break;case ENEMY_ATTACK:System.out.println("變為小馬里奧");mario.setState(new SmallMario(mario));break;case FALL_INTO_PIT:System.out.println("馬里奧去世了");mario.setState(new DeadMario(mario));break;}}
}
// 實現火焰馬里奧狀態
class FireMario implements MarioState {private Mario mario;public FireMario(Mario mario) {this.mario = mario;}@Overridepublic void handleEvent(Event event) {switch (event) {case MUSHROOM:System.out.println("保持火焰馬里奧");break;case FIRE_FLOWER:System.out.println("保持火焰馬里奧");break;case ENEMY_ATTACK:System.out.println("變為大馬里奧");mario.setState(new BigMario(mario));break;case FALL_INTO_PIT:System.out.println("馬里奧去世了");mario.setState(new DeadMario(mario));break;}}
}
// 定義馬里奧類,作為狀態的上下文
class Mario {private MarioState state;public Mario() {state = new SmallMario(this);}public void setState(MarioState state) {this.state = state;}public void handleEvent(Event event) {state.handleEvent(event);}
}
// 測試類
public class MarioDemo {public static void main(String[] args) {Mario mario = new Mario();mario.handleEvent(Event.MUSHROOM); // 變為大馬里奧mario.handleEvent(Event.FIRE_FLOWER); // 變為火焰馬里奧mario.handleEvent(Event.ENEMY_ATTACK); // 變為大馬里奧}
}

????????在這個簡化示例中,我們定義了 MarioState 接口以及實現了 DeadMario 、SmallMario 、 BigMario FireMario 類,分別表示馬里奧的四種形態。每個形態類實現了 handleEvent 方法,用于處理不同的游戲事件并根據有限狀態機規 則進行狀態轉換。

????????Mario 類作為狀態的上下文,用于管理和切換馬里奧的狀態。它有一個 setState方法,用于更新當前狀態。 handleEvent 方法將事件傳遞給當前狀態,以便根據事件執行相應的狀態轉換。

????????在 MarioDemo 測試類中,我們創建了一個 Mario 實例,并通過調用handleEvent 方法模擬游戲中的事件。通過運行這個測試類,你可以觀察到馬里奧根據有限狀態機的規則在不同形態之間切換。

????????這個簡化示例展示了如何使用有限狀態機來實現馬里奧角色的形態變化。在實際游戲開發中,你可能需要考慮更多的事件和狀態,以及與游戲引擎或框架集成的方式。不過,這個示例可以幫助你理解有限狀態機在游戲中的應用。

六、迭代器模式

? ? ? ? 迭代器模式,它用來遍歷集合對象,不過,很多編程語言都將迭代器作為一個基礎的類庫,直接提供出來了。在平時的開發中,特別是業務開發,我們直接使用即可,很少會自己去實現一個迭代器。不過弄懂原理能幫助我們更好的使用這些工具類。

? ? ? ? 不怎么用,省略,需要可以自行查詢。

????????

七、訪問者模式

? ? ? ? 1、概述和原理

? ? ? ? 訪問者設計模式(Visitor Pattern)是一種行為型設計模式,它允許你再不修改現有類結構的情況下,為類添加新的操作,這種模式可以實現良好的解耦和擴展性,尤其適用于現有類層次結構中添加新的功能的情況。

? ? ? ? 訪問者模式主要包含以下角色:
????????1. 訪問者(Visitor):定義一個訪問具體元素的接口,為每種具體元素類型聲明一個訪問操作。
????????2. 具體訪問者(ConcreteVisitor):實現訪問者接口,為每種具體元素提供具體的訪問操作實現。
????????3. 元素(Element):定義一個接口,聲明接受訪問者的方法。
????????4. 具體元素(ConcreteElement):實現元素接口,提供接受訪問者的具體實現。
????????5. 對象結構(ObjectStructure
):包含一個元素集合,提供一個方法以遍歷這些元素并讓訪問者訪問它們。

????????以下是一個簡單的訪問者模式示例:

????????假設我們有一個表示計算機組件的類層次結構(如 CPU、內存和硬盤等),我們需要為這些組件實現一個功能,比如展示它們的詳細信息。使用訪問者模式,我們可以將【展示詳細信息】的功能與【組件類】分離,從而實現解耦和擴展性。
????????1、不同的元素(被訪問的對象)可以接收不同的訪問者。
????????2、不同的訪問者會對不同的被訪問者產生不同的行為。
????????3、如果想要擴展,則獨立重新實現訪問者接口,產生一個新的具體訪問者就可以了。
????????4、他實際解耦的是【被訪問者】和【對被訪問者的操作】。

????????簡單理解就是不同的訪問者,到了同一個被訪問對象的家里會干不同的事。這個【事】就是行為,通過訪問者模式,我們可以將行為和對象分離解耦,如下圖。

????????下邊是一個使用了訪問者模式的案例:
// 訪問者接口
interface ComputerPartVisitor {// 訪問 Computer 對象void visit(Computer computer);// 訪問 Mouse 對象void visit(Mouse mouse);// 訪問 Keyboard 對象void visit(Keyboard keyboard);
}
// 具體訪問者
class ComputerPartDisplayVisitor implements ComputerPartVisitor {// 訪問 Computer 對象@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");}// 訪問 Mouse 對象@Overridepublic void visit(Mouse mouse) {System.out.println("Displaying Mouse.");}// 訪問 Keyboard 對象@Overridepublic void visit(Keyboard keyboard) {System.out.println("Displaying Keyboard.");}
}
// 元素接口
interface ComputerPart {// 接受訪問者的訪問void accept(ComputerPartVisitor computerPartVisitor);
}
// 具體元素
class Computer implements ComputerPart {// 子元素數組ComputerPart[] parts;public Computer() {// 初始化子元素數組parts = new ComputerPart[]{new Mouse(), new Keyboard()};}// 接受訪問者的訪問@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {// 遍歷所有子元素并接受訪問者的訪問for (int i = 0; i < parts.length; i++) {parts[i].accept(computerPartVisitor);}// 訪問 Computer 對象本身computerPartVisitor.visit(this);}
}
// 具體元素:鼠標
class Mouse implements ComputerPart {// 接受訪問者的訪問@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {// 訪問 Mouse 對象computerPartVisitor.visit(this);}
}
// 具體元素:鍵盤
class Keyboard implements ComputerPart {// 接受訪問者的訪問@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {// 訪問 Keyboard 對象computerPartVisitor.visit(this);}
}
// 客戶端代碼
public class VisitorPatternDemo {public static void main(String[] args) {// 創建一個 Computer 對象ComputerPart computer = new Computer();// 創建一個具體訪問者ComputerPartVisitor visitor = new ComputerPartDisplayVisitor();// 讓 Computer 對象接受訪問者的訪問computer.accept(visitor);}
}

????????在這個示例中,我們定義了一個表示計算機組件的類層次結構,包括 Computer 、Mouse 和 Keyboard 。這些類實現了 ComputerPart 接口,該接口聲明了一個接受訪問者的方法。我們還定義了一個 ComputerPartVisitor 接口,用于訪問這些計算機組件,并為每種組件類型聲明了一個訪問操作。

????????ComputerPartDisplayVisitor 類實現了 ComputerPartVisitor 接口,為每種計算機組件提供了展示詳細信息的功能。在客戶端代碼中,我們創建了一個Computer 對象和一個 ComputerPartDisplayVisitor 對象。當我們調用computer.accept() 方法時,計算機的所有組件都會被訪問者訪問,并顯示相應的詳細信息。

????????這個示例展示了如何使用訪問者模式將功能與類結構分離,實現解耦和擴展性。如果我們需要為計算機組件添加新功能,只需創建一個新的訪問者類,而無需修改現有的組件類。這使得在不影響現有代碼的情況下,為系統添加新功能變得容易。

// 添加一個更新計算機部件的訪問者實現
class ComputerPartUpdateVisitorImpl implements ComputerPartVisitor {// 訪問 Computer 對象并執行更新操作@Overridepublic void visit(Computer computer) {System.out.println("Updating Computer.");}// 訪問 Mouse 對象并執行更新操作@Overridepublic void visit(Mouse mouse) {System.out.println("Updating Mouse.");}// 訪問 Keyboard 對象并執行更新操作@Overridepublic void visit(Keyboard keyboard) {System.out.println("Updating Keyboard.");}
}
// 客戶端代碼,幾乎不用任何修改
public class VisitorPatternDemo {public static void main(String[] args) {// 創建一個 Computer 對象ComputerPart computer = new Computer();// 創建一個具體訪問者ComputerPartVisitor visitor = new ComputerPartUpdateVisitorImpl();// 讓 Computer 對象接受訪問者的訪問computer.accept(visitor);}
}

????????訪問者模式可以算是 23 種經典設計模式中最難理解的幾個之一。因為它難理解、難實現,應用它會導致代碼的可讀性、可維護性變差,所以,訪問者模式在實際的軟件開發中很少被用到,在沒有特別必要的情況下,建議你不要使用訪問者模式。

? ? ? ? 2、使用場景

? ? ? ? 2.1 抽象語法樹

????????訪問者模式在實際項目中的一個常見使用場景是處理抽象語法樹(AST)。例如,在編譯器或解釋器中,我們需要處理不同類型的語法結構,如聲明、表達式、循環等。 使用訪問者模式,我們可以將處理這些結構的功能與結構類分離,實現解耦和擴展性。
????????以下是一個簡單的示例,展示了如何使用訪問者模式處理抽象語法樹

// AST 節點基類
abstract class AstNode {// 接受訪問者的方法abstract void accept(AstVisitor visitor);
}
// 訪問者接口
interface AstVisitor {// 訪問表達式節點的方法void visit(ExpressionNode node);// 訪問數字節點的方法void visit(NumberNode node);// 訪問加法節點的方法void visit(AdditionNode node);
// 省略其他節點
}
// 數字節點,表示一個整數值
class NumberNode extends AstNode {int value;// 構造方法,接收一個整數作為值NumberNode(int value) {this.value = value;}// 實現基類的 accept 方法,接受訪問者void accept(AstVisitor visitor) {visitor.visit(this);}
}
// 加法節點,表示兩個子節點的相加
class AdditionNode extends AstNode {AstNode left;AstNode right;// 構造方法,接收兩個子節點AdditionNode(AstNode left, AstNode right) {this.left = left;this.right = right;}// 實現基類的 accept 方法,接受訪問者void accept(AstVisitor visitor) {visitor.visit(this);}
}
// 表達式節點,包含一個子節點
class ExpressionNode extends AstNode {AstNode node;// 構造方法,接收一個子節點ExpressionNode(AstNode node) {this.node = node;}// 實現基類的 accept 方法,接受訪問者void accept(AstVisitor visitor) {visitor.visit(this);}
}
????????現在,我們可以創建一個實現了 AstVisitor 接口的類,用于遍歷 AST 并計算其結果:
class AstEvaluator implements AstVisitor {int result;AstEvaluator() {result = 0;}void visit(ExpressionNode node) {node.node.accept(this);}void visit(NumberNode node) {result = node.value;}void visit(AdditionNode node) {node.left.accept(this);int leftValue = result;node.right.accept(this);int rightValue = result;result = leftValue + rightValue;}
}

????????最后,我們可以使用這個訪問者類計算一個簡單的 AST

public class Main {public static void main(String[] args) {// 創建一個簡單的 AST:(2 + 3)AstNode ast = new ExpressionNode(new AdditionNode(new NumberNode(2),new NumberNode(3)));// 創建一個訪問者實例AstEvaluator evaluator = new AstEvaluator();// 使用訪問者計算 AST 的結果ast.accept(evaluator);// 輸出計算結果System.out.println("AST 的結果是: " + evaluator.result);}
}
????????這個示例將輸出 AST 的結果是 : 5

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

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

相關文章

大模型學習八:?Sealos 私有化部署之VMware 安裝ubuntu22.04 虛擬機安裝(實操)

一、說明 windows 11 ubuntu22.04.5 安裝5個虛擬機&#xff0c;3個master 2個node 二、安裝 Vmware 17&#xff08;沒成功&#xff0c;但你可以成功&#xff09; 我的電腦配置比較舊&#xff0c;直接提示處理器不支持xsave 無法打開虛擬機的電源&#xff0c;網上方法試過了…

Win32++ 使用初探

文章目錄 1. 環境要求2. Win32安裝3. 項目創建3.1 項目創建&#xff08;1&#xff09;直接使用Win32里的示例Sample&#xff08;2&#xff09;自行創建項目 最近想用 VC寫些 UI&#xff0c;但又不太想用 MFC&#xff0c;正好對界面要求不太高&#xff0c;就使用了一下 Win3…

R 語言科研繪圖第 38 期 --- 餅狀圖-玫瑰

在發表科研論文的過程中&#xff0c;科研繪圖是必不可少的&#xff0c;一張好看的圖形會是文章很大的加分項。 為了便于使用&#xff0c;本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中&#xff0c;獲取方式&#xff1a; R 語言科研繪圖模板 --- sciRplothttps://mp.…

Linux驅動開發進階(六)- 多線程與并發

文章目錄 1、前言2、進程與線程3、內核線程4、底半步機制4.1、軟中斷4.2、tasklet4.3、工作隊列4.3.1、普通工作項4.3.2、延時工作項4.3.3、工作隊列 5、中斷線程化6、進程6.1、內核進程6.2、用戶空間進程 7、鎖機制7.1、原子操作7.2、自旋鎖7.3、信號量7.4、互斥鎖7.5、comple…

第四節:React Hooks進階篇-useEffect依賴項為空數組[]與不寫的區別

陷阱題&#xff1a;閉包問題、Stale Closure舉例 一、依賴項為空數組[]與不寫的核心區別 行為空數組[]不寫依賴項執行時機僅在組件掛載時執行一次&#xff08;類似componentDidMount&#xff09;組件每次渲染后都執行&#xff08;類似componentDidUpdate&#xff09;更新觸發…

【第39節】windows編程:打造MFC版本任務管理器

目錄 一、項目概述 二、項目開發的各種功能關鍵 2.1 進程信息的獲取 2.2 線程信息的獲取 2.3 進程模塊信息的獲取 2.3.1 模塊快照 2.3.2 枚舉模塊 2.4 進程堆信息的獲取 2.5 窗口信息的獲取 2.6 文件信息的獲取 2.7 內存信息和CPU占用率的獲取 2.7.1 內存信息相關結…

計算軸承|滾動軸承故障頻率

一、軸承故障頻率概述 在旋轉機械故障診斷中&#xff0c;軸承故障頻率&#xff08;BPFO、BPFI、BSF、FTF&#xff09;是重要的分析依據。通過計算這些特征頻率&#xff0c;可以幫助工程師&#xff1a; 識別軸承故障類型&#xff08;內圈/外圈/滾動體故障&#xff09;制定振動…

【數據結構與算法】ArrayList 和 順序表

文章目錄 &#x1f332;List&#x1f332;1. 線性表&#x1f332;2. 順序表&#x1f33f;2.1 MyArrayList2.1.1 類中重寫所有接口方法1.新增元素2.在pos位置新增元素(指定位置)3.判定是否包含了某個特定元素 4.查找特定元素對應的位置 5.獲取pos下標的元素 6.給pos位置的元素替…

OceanBase 推出單機版 ,為中小規模業務提供高性價比方案

近日&#xff0c;OceanBase正式推出了全新的單機版數據庫。這款產品基于OceanBase自主研發的單機分布式一體化架構&#xff0c;具有精簡的架構設計和出色的兼容性&#xff0c;能夠為中小規模業務場景提供高性價比的數據庫解決方案&#xff0c;充分滿足客戶在不同業務規模下的多…

如何在 Vue 3 中實現百度地圖位置選擇器組件

如何在 Vue 3 中實現百度地圖位置選擇器組件 前言 在開發前端應用時&#xff0c;地圖選擇器是一個非常常見的需求。尤其是在一些需要用戶選擇地址的場景&#xff0c;如電商平臺、旅游網站、酒店預定等&#xff0c;百度地圖組件能提供準確的地理位置服務。在本文中&#xff0c…

Python中如何用正則表達式精準匹配IP地址?

在網絡編程和數據處理時&#xff0c;我們經常需要從文本中提取或驗證IP地址。Python的正則表達式(re模塊)是完成這個任務的利器。但你知道怎么寫才能準確匹配各種合法的IP地址嗎&#xff1f;今天我們就來詳細探討這個問題。 為什么需要IP正則表達式&#xff1f; 假設你正在分…

spring--聲明式事務

聲明式事務 1、回顧事務 要么都成功&#xff0c;要么都失敗&#xff01; 事務在項目開發中&#xff0c;十分重要&#xff0c;涉及數據的一致性問題 確保完整性和一致性 事務ACID&#xff1a; 原子性&#xff1a;事務是原子性操作&#xff0c;由一系列動作組成&#xff0c;…

Kotlin 學習-集合

/*** kotlin 集合* List:是一個有序列表&#xff0c;可通過索引&#xff08;下標&#xff09;訪問元素。元素可以在list中出現多次、元素可重復* Set:是元素唯一的集合。一般來說 set中的元素順序并不重要、無序集合* Map:&#xff08;字典&#xff09;是一組鍵值對。鍵是唯一的…

WPF 五子棋項目文檔

WPF 五子棋項目文檔 1. 項目概述 本項目是一個使用 Windows Presentation Foundation (WPF) 技術棧和 C# 語言實現的桌面版五子棋&#xff08;Gomoku&#xff09;游戲。它遵循 MVVM&#xff08;Model-View-ViewModel&#xff09;設計模式&#xff0c;旨在提供一個結構清晰、可…

計算機操作系統——死鎖(詳細解釋和處理死鎖)

系列文章目錄 計算機操作系統-計算機系統中的死鎖 文章目錄 系列文章目錄前言一、資源問題&#xff1a; 計算機系統當中的死鎖&#xff1a; 二、死鎖的定義、必要條件和處理方法&#xff1a; 1.死鎖的定義&#xff1a;2.產生死鎖的必要條件&#xff1a;3.處理死鎖的方法&#…

Springboot項目正常啟動,訪問資源卻出現404錯誤如何解決?

我在自己的springboot項目中的啟動類上同時使用了SprinBootApplication和ComponentScan注解, 雖然項目能夠正常啟動,但是訪問資源后,返回404錯誤,隨后在啟動類中輸出bean,發現controller創建失敗: 而后我將ComponentScan去掉后資源就能訪問到了. 原因 SprinBootApplication本身…

第十五屆藍橋杯C/C++B組省賽真題講解(分享去年比賽的一些真實感受)

試題A——握手問題 一、解題思路 直接用高中學的排列組合思路 二、代碼示例 #include<bits/stdc.h> using namespace std; int fun(int n) {int sum0;for(int i0;i<n;i){for(int ji1;j<n;j)sum; } return sum; } int main() {cout<<fun(50)-fun(7); }三、…

動態規劃(6)——01背包問題

歡迎來到博主的專欄&#xff1a;算法解析 博主ID&#xff1a;代碼小號 文章目錄 牛客網——【模板】01背包題目解析題目1算法原理題目1題解代碼。問題2算法原理問題2題解代碼01背包問題的滾動數組優化 牛客網——【模板】01背包 題目解析 關于I/O相關的東西博主就不多贅述了&a…

TQTT_KU5P開發板教程---實現流水燈

文檔實現功能介紹 本文檔是學習本開發板的基礎&#xff0c;通過設置計數器使led0到led7依次閃爍&#xff0c;讓用戶初步認識vivado基本的開發流程以及熟悉項目的創建。本開發板的所有教程所使用的軟件都是vivado2024.1版本的。可以根據網上的教程下載與安裝。 硬件資源 此次教程…

Spring 中的 @Cacheable 緩存注解

1 什么是緩存 第一個問題&#xff0c;首先要搞明白什么是緩存&#xff0c;緩存的意義是什么。 對于普通業務&#xff0c;如果要查詢一個數據&#xff0c;一般直接select數據庫進行查找。但是在高流量的情況下&#xff0c;直接查找數據庫就會成為性能的瓶頸。因為數據庫查找的…