設計模式-行為型模式(詳解)

模板方法

模板方法模式,它在一個抽象類中定義了一個算法(業務邏輯)的骨架,具體步驟的實現由子類提供,它通過將算法的不變部分放在抽象類中,可變部分放在子類中,達到代碼復用和擴展的目的。

  • 復用: 所有子類可以直接復用父類提供的模板方法,即上面提到的不變的部分。
  • 擴展: 子類可以通過模板定義的一些擴展點就行不同的定制化實現。

我們來看一下示例代碼就很清晰了

abstract class AbstractClass {   //模板類// 模板方法public final void templateMethod() {primitiveOperation1();primitiveOperation2();hook();}// 基本操作(抽象方法)protected abstract void primitiveOperation1();protected abstract void primitiveOperation2();// 鉤子方法(可選的操作,提供默認實現)protected void hook() {}
}
class ConcreteClassA extends AbstractClass {  //具體方法A@Overrideprotected void primitiveOperation1() {System.out.println("ConcreteClassA: primitiveOperation1");}@Overrideprotected void primitiveOperation2() {System.out.println("ConcreteClassA: primitiveOperation2");}
}
class ConcreteClassB extends AbstractClass {  //具體方法B@Overrideprotected void primitiveOperation1() {System.out.println("ConcreteClassB: primitiveOperation1");}@Overrideprotected void primitiveOperation2() {System.out.println("ConcreteClassB: primitiveOperation2");}@Overrideprotected void hook() {System.out.println("ConcreteClassB: hook");}
}

場景

應用場景:
例如支付場景,需要有支付寶、銀行卡、微信支付多種方式,可以定義支付的骨架,骨架里包括一些獲取訂單、驗證密碼、執行支付、發送短信的邏輯,像驗證密碼這些公共的就由骨架來提供,執行支付就由子類來獨立實現。

除此之外,支付場景,可能也會涉及到工廠模式,不同的支付方式,利用工廠模式不同的支付對象,再調用支付對象實現不同的功能。

策略模式

策略模式是一種行為型設計模式,提供一個策略接口,并獨立實現各種具體策略,允許在運行時動態選擇具體策略,從而實現更加靈活的代碼結構。該模式的中心不是如何實現算法,而是如何組織、調用這些算法,方便調用方在針對不同場景靈活切換不同的策略。

// 策略的定義
public interface Strategy {void execute(User user); 
}
//具體策略A
public class AStrategy implements Strategy{void execute(User user) {System.out.println("Executing Strategy A " + user.getName());}
}
//具體策略B
public class BStrategy implements Strategy{void execute(User user) {System.out.println("Executing Strategy B " + user.getName());}
}// 策略集合的創建
public class StrategyFactory {private static final Map<String, Strategy> strategies = new HashMap<>();static {strategies.put("A", new AStrategy());strategies.put("B", new BStrategy());}public static Strategy getStrategy(OrderType type) {return strategies.get(type);} 
}// 策略的使用
public class xxService {public void execute(User user) {String type = user.getType();Strategy strategy = StrategyFactory.getStrategy(type);return strategy.execute(user);}
}

可以看到,上述的代碼通過使用策略模式,可以將不同的算法策略封裝起來,并根據 user 的類型在運行時動態選擇具體的算法策略,從而提高系統的靈活性和可擴展性。

可以用在例如多種支付方式的切換、不同排序算法的切換等多策略實現的場景。

責任鏈模式

責任鏈模式允許將多個對象連接成一條鏈,并且沿著這條鏈傳遞請求,讓多個對象都有機會處理這個請求,請求會順著鏈傳遞,直到某個對象處理它為止。

在很多場景都能看到責任鏈模式,比如日志的處理,不同級別不同輸出。再比如 Spring 過濾器的 Chain 也是責任鏈模式。

下面是一個簡單的日志處理示例代碼。

  • 日志處理器有三種類型: 控制臺日志處理器(ConsoleLogger)、文件日志處理器(FileLogger)、錯誤日志處理器(ErrorLogger)。
  • 日志處理器按照優先級進行處理,如果當前處理器不能處理,則將請求傳遞給下一個處理器。
// 責任鏈模式的抽象日志類
abstract class Logger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;protected Logger nextLogger;   //日志中可以存下一個日志public void setNextLogger(Logger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}if (nextLogger != null) {nextLogger.logMessage(level, message);}}protected abstract void write(String message);
}// 具體處理器類:控制臺日志處理器
class ConsoleLogger extends Logger {public ConsoleLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("Standard Console::Logger: " + message);}
}
// 具體處理器類:文件日志處理器
class FileLogger extends Logger {public FileLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("File::Logger: " + message);}
}
// 具體處理器類:錯誤日志處理器
class ErrorLogger extends Logger {public ErrorLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("Error Console::Logger: " + message);}
}// 客戶端代碼
public class ChainPatternDemo {private static Logger getChainOfLoggers() {  //獲取日志責任鏈Logger errorLogger = new ErrorLogger(Logger.ERROR);Logger fileLogger = new FileLogger(Logger.DEBUG);Logger consoleLogger = new ConsoleLogger(Logger.INFO);errorLogger.setNextLogger(fileLogger);  //存下一個日志fileLogger.setNextLogger(consoleLogger);   //存再下一個日志return errorLogger;  //最后返回}public static void main(String[] args) {Logger loggerChain = getChainOfLoggers();loggerChain.logMessage(Logger.INFO, "mianshiya.com");loggerChain.logMessage(Logger.DEBUG, "小程序:面試鴨");loggerChain.logMessage(Logger.ERROR, "網頁端:mianshiya.com");}
}

觀察者模式

觀察者模式其實也稱為發布訂閱模式,它定義了對象之間的一種一對多的依賴關系,讓多個觀察者對象 同時監聽某一個主題對象。當主題對象狀態發生變化時,它會通知所有觀察者對象。

發布訂閱與觀察者模式的區別**:發布訂閱引入了第三方組件來維護發布者和訂閱者的關系,他們之間不直接通信,做到了真正解耦。**

觀察者模式的組成部分

  • Subject(主題/被觀察者): 狀態發生變化時,通知所有注冊的觀察者
  • Observer(觀察者): 接收來自主題的更新通知,并進行相應的操作。
  • ConcreteSubject(具體主題): 實現具體的主題對象,保存需要被觀察的狀態。
  • ConcreteObserver(具體觀察者): 實現具體的觀察者對象,更新自己以與主題的狀態同步

我們以一個新聞發布系統來理解下觀察者模式。

1)定義接口

? 新聞發布者(Subject)可以發布新聞,觀察者(Observer)是訂閱者,希望獲取新聞更新

2)實現具體類

  • 具體新聞發布者(Concrete Subject)維護一個訂閱者列表,并在發布新聞時通知他們
  • 具體觀察者(Concrete Observer)如報紙、新聞網站等,實現更新方法來展示新聞

3)訂閱和退訂

? 訂閱者可以訂閱(注冊)或退訂(注銷)新聞發布者的新聞。

4)發布新聞

? 當新聞發布者有新新聞時,"觀察者更新自己的新聞內容。它通知所有訂閱的觀察者

5)客戶端代碼

? 客戶端代碼創建新聞發布者和觀察者對象,訂閱者選擇訂新聞,并在接收到新聞時更新顯示。

// 定義觀察者接口
interface Observer {void update(String news);
}
// 定義主題接口
interface Subject {void attach(Observer o);void detach(Observer o);void notifyObservers();
}
// 具體新聞發布者
class NewsPublisher implements Subject {private List<Observer> observers = new ArrayList<>();public void attach(Observer o) {observers.add(o);}public void detach(Observer o) {observers.remove(o);}public void notifyObservers() {for (Observer observer : observers) {observer.update("新聞更新");}}public void publishNews() {// 假設這里是新聞發布邏輯,會通知發布者里面集合的觀察者notifyObservers();}
}// 具體觀察者
class NewsPaper implements Observer {public void update(String news) {System.out.println("新報 " + news);}
}// 客戶端代碼
public class Client {public static void main(String[] args) {NewsPublisher publisher = new NewsPublisher();  //發布者Observer newsPaper = new NewsPaper();   //觀察者publisher.attach(newsPaper);     //導入觀察者publisher.publishNews();        //發布新聞publisher.detach(newsPaper);    //移除觀察者publisher.publishNews(); // 此時報紙訂閱者不會接收到新聞}
}

例如消息隊列、 Spring 內的監聽器機制等都是其應用場景

迭代器模式

迭代器模式,它提供一種方法順序訪問一個集合對象中的各個元素,而又不暴露該對象(可能是數組、鏈表、樹等等)的內部實現。

將遍歷邏輯與集合對象的實現分離,提供一致的遍歷方式,使得代碼統一化,在不改變遍歷代碼的情況下就能替換底層集合實現。

像 Java 的java.util.Iterator接口和Iterable接口是迭代器模式的直接應用。所有集合類(如ArrayList、HashSet、LinkedList 等)都實現了 Iterable 接口,并提供了 iterator() 方法來獲取迭代器,例如,遍歷 ArrayList 中的元素:

List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {System.out.println(iterator.next());
}

再比如 JDBC 的ResultSet接口遍歷數據庫査詢結果,也是迭代器模式的實現。

迭代器模式的組成部分

  • lterator(迭代器接口): 定義訪問和歷元素的接口
  • Aggregate(聚合接口): 定義創建迭代器的接口
  • Concretelterator(具體迭代器): 實現迭代器接口,負責遍歷聚合對象中的元素
  • ConcreteAggregate(具體聚合類): 實現聚合接口,返回一個具體的迭代器實例。

我們來簡單實現一個迭代器

//定義迭代器接口
interface Iterator<T> {boolean hasNext();T next();
}
//定義聚合接口
interface Aggregate<T> {Iterator<T> createIterator();
}//定義具體迭代器
class ConcreteIterator<T> implements Iterator<T> {private List<T> items;private int position = 0;  //當前遍歷位置public ConcreteIterator(List<T> items) {this.items = items;}@Overridepublic boolean hasNext() {    //如果進行集合遍歷時位置<集合大小,則返回truereturn position < items.size();}@Overridepublic T next() {  //獲取當前遍歷位置的下一個元素return items.get(position++);}
}
//定義具體聚合類
class ConcreteAggregate<T> implements Aggregate<T> {private List<T> items = new ArrayList<>();public void addItem(T item) {   //添加元素方法items.add(item);}@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(items);}
}
//簡單使用
public class Client {public static void main(String[] args) {ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();aggregate.addItem("Item 1");    //添加集合元素aggregate.addItem("Item 2");aggregate.addItem("Item 3");Iterator<String> iterator = aggregate.createIterator(); //返回對應該集合的迭代器while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

命令模式

命令模式(Command Pattern)是一種行為設計模式,它將請求封裝成對象,使得請求參數化,便于對請求排隊或記錄請求日志,以及支持可撤銷的操作。

簡單看下以開關燈為例實現命令模式的代碼,更容易理解上面那段含義:

// 命令接口
interface Command {void execute();
}
// 接收者
class Light {   public void on() {    //用于控制燈光的開關System.out.println("The light is on.");}public void off() {System.out.println("The light is off.");}
}// 具體命令   開燈
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}
}
// 具體命令   關燈
class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}
}
// 調用者,傳入了開關命令,因此可以開關燈
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}// 客戶端代碼
public class Client {public static void main(String[] args) {Light light = new Light();   Command lightOn = new LightOnCommand(light);  //開燈Command lightOff = new LightOffCommand(light);   //關燈RemoteControl remote = new RemoteControl();remote.setCommand(lightOn);     remote.pressButton();   //開燈remote.setCommand(lightOff);remote.pressButton();    //關燈}
}

狀態模式

狀態模式 允許對象在其內部狀態發生改變時改變其行為,將狀態的行為封裝在獨立的類中,并將這些狀態對象組合在擁有狀態的對象中,這樣就可以在狀態改變時切換狀態對象,從而改變對象的行為

它主要是狀態機的一種實現方式,狀態機可分為: 狀態、事件、動作三個部分。事件的觸發就會導致狀態的改變,并且可作出一定的動作(也可以沒有動作,只有狀態的改變)

// 定義狀態接口
interface State {void handle(Context context);
}
// 上下文環境,狀態模式的核心,它持有一個 State 對象,并提供了 setState 方法來改變當前狀態
class Context {private State state;public Context(State state) {this.state = state;}public void setState(State state) {this.state = state;}public void request() {state.handle(this);}
}
// 具體實現類
//AB每個類在處理請求時都會打印一條消息,并且會改變上下文 Context 的狀態為另一種狀態
class ConcreteStateA implements State {@Overridepublic void handle(Context context) {System.out.println("State A is handling the request.");context.setState(new ConcreteStateB());}
}
class ConcreteStateB implements State {@Overridepublic void handle(Context context) {System.out.println("State B is handling the request.");context.setState(new ConcreteStateA());}
}public class Client {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());   //新建A狀態環境context.request(); // State A is handling the request.   //請求A狀態,然后設置當前狀態為Bcontext.request(); // State B is handling the request.context.request(); // State A is handling the request.context.request(); // State B is handling the request.}
}

中介者模式

中介模式通過引入了一個中介對象,來封裝一組對象之間的交互,來避免對象之間的直接交互。通過引入一個中介者對象,使對象之間的關系變得簡單且易于維護。

聽起來不就是和現實生活中的中介一樣嘛。

引入中介模式的原因:多對象交互可能會使得關系圖很混亂,代碼也不清晰,讓多對象都和中介交互就能避免這點

image-20240928194712824

聊天室實現其實就是運用了中介模式。信息的傳遞都由服務器這個中介來做,所有用戶都把消息發給服務器,不然如果點對點傳輸大家可以想象下有多復雜。我們可以簡單的看下聊天室的實現:

interface ChatMediator {       //中介者接口void sendMessage(String message, User user);void addUser(User user);
}
class ChatMediatorImpl implements ChatMediator { //具體中介者private List<User> users;   //存儲加入的用戶public ChatMediatorImpl() {this.users = new ArrayList<>();}@Overridepublic void addUser(User user) {this.users.add(user);}@Overridepublic void sendMessage(String message, User user) {for (User u : this.users) {if (u != user) {u.receive(message);}}}
}abstract class User {       //抽象用戶protected ChatMediator mediator;protected String name;public User(ChatMediator mediator, String name) {this.mediator = mediator;this.name = name;}public abstract void send(String message);public abstract void receive(String message);
}class UserImpl extends User {    //用戶public UserImpl(ChatMediator mediator, String name) {super(mediator, name);}@Overridepublic void send(String message) {System.out.println(this.name + " sends: " + message);mediator.sendMessage(message, this);}@Overridepublic void receive(String message) {System.out.println(this.name + " receives: " + message);}
}
public class ChatClient {    //客戶端public static void main(String[] args) {ChatMediator mediator = new ChatMediatorImpl();User user1 = new UserImpl(mediator, "Alice");User user2 = new UserImpl(mediator, "Bob");User user3 = new UserImpl(mediator, "Charlie");mediator.addUser(user1);   //用戶加入中介mediator.addUser(user2);mediator.addUser(user3);user1.send("Hello, everyone!");}
}

訪問者模式

訪問者模式它將數據結構與操作分離,使得你可以在不改變數據結構的前提下定義新的操作。訪問者模式通過將操作封裝到獨立的訪問者對象中,使得新的操作可以很容易地添加到系統中。

例如對象序列化場景,比如需要將對象轉成 JSON 或者 XML 等格式,利用訪問者模式將對象的結構和序列化操作分離,這樣就能很方便的擴展新的序列化格式。先看下示例代碼:

//訪問者接口(類比序列化接口)
interface Visitor {void visit(ElementA element);void visit(ElementB element);
}
//具體訪問者類(類比具體序列化實現)
class ConcreteVisitor implements Visitor {@Overridepublic void visit(ElementA element) {System.out.println("Processing ElementA: " + element.getName());}@Overridepublic void visit(ElementB element) {System.out.println("Processing ElementB: " + element.getName());}
}//需要對序列化的元素接口
interface Element {void accept(Visitor visitor);
}// 具體被序列化的元素A
class ElementA implements Element {private String name;public ElementA(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}
// 具體被序列化的元素B
class ElementB implements Element {private String name;public ElementB(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}//對象結構,包含很多元素
class ObjectStructure {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 客戶端代碼
public class Client {public static void main(String[] args) {// 組裝對象ObjectStructure objectStructure = new ObjectStructure();objectStructure.addElement(new ElementA("Element A1"));objectStructure.addElement(new ElementB("Element B1"));objectStructure.addElement(new ElementA("Element A2"));//訪問者 (如果是序列化場景,ConcreteVisitor 可以當做 JSON 序列化)Visitor visitor = new ConcreteVisitor();objectStructure.accept(visitor);// 假設后面要替換 xml 序列化,僅需新建 xml 的訪問者,然后傳入到對象內部即可Visitor visitorXML = new XMLVisitor();objectStructure.accept(visitorXML);}
}

可以看到,將數據結構和操作分離開之后,如果要替換具體的操作,僅需新增一個操作即可,不需要修改任何數據結構,這就符合開閉原則,也保證了類的職責單一。

備忘錄模式

備忘錄模式指的是在不違背封裝原則的前提下,捕獲對象內部的狀態,將其保存在外部,便于后面對象恢復之前的狀態,使得系統更具靈活性和可維護性。

聽來像不像保留個快照作為備份,后面基于這個快照進行恢復? 所以備忘錄模式其實也叫快照模式。主要用于撤銷、恢復等場景。

來看下示例代碼,我先大致解釋一下幾個類的含義:

  • Memento,存儲狀態的備忘錄
  • Originator,需要備份狀態的對象類
  • Caretaker,管理者,僅保存備忘錄
// 備忘錄類
class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}
}// 需要備份狀態的對象類
class Originator {private String state;public void setState(String state) {this.state = state;System.out.println("State set to: " + state);}public String getState() {return state;}public Memento createMemento() {return new Memento(state);}public void restoreMemento(Memento memento) {this.state = memento.getState();System.out.println("State restored to: " + state);}
}
//管理存儲類
class Caretaker {private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}
}//客戶端類
public class Client {public static void main(String[] args) {Originator originator = new Originator();  //對象類Caretaker caretaker = new Caretaker();       //存儲類originator.setState("State1");caretaker.setMemento(originator.createMemento()); //保存快照originator.setState("State2");System.out.println("Current State: " + originator.getState());originator.restoreMemento(caretaker.getMemento());    //恢復快照System.out.println("Restored State: " + originator.getState());}
}

如果直接利用 set 方法修改內部狀態,就違反了封裝的原則,因為如果你暴露了 set 方法,則對象內部的狀態很可能被別的業務調用修改了。而 restoreMemento 是一個很清晰的方法定義,即恢復之前的狀態,不會被亂用。這也是備忘錄模式的前提,不違反封裝原則。

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

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

相關文章

STM32中的IIC協議和OLED顯示屏

串口通信協議的缺點 串口通信通常需要至少三條線&#xff08;TX、RX和GND&#xff09;&#xff0c;而 I2C 總線僅需要兩條信號線&#xff08;SDA和SCL&#xff09;&#xff1b; 串口通信僅支持一對一通信&#xff0c;而 I2C 總線支持多機通信&#xff0c;允許單個主機與多個從…

30個性能優化方案

1.用String.format拼接字符串 不知道你有沒有拼接過字符串&#xff0c;特別是那種有多個參數&#xff0c;字符串比較長的情況。 比如現在有個需求&#xff1a;要用get請求調用第三方接口&#xff0c;url后需要拼接多個參數。 以前我們的請求地址是這樣拼接的&#xff1a; S…

docker中部署Universal Media Server (UMS)

Universal Media Server (UMS) 本身主要是作為桌面服務程序開發的&#xff08;主要面向 Java GUI DLNA 播放&#xff09;&#xff0c;但確實可以通過 Docker 進行部署。雖然官方沒有提供 Docker 鏡像&#xff0c;但社區有一些可用的方式可以在 Docker 中運行它。 下面是一個可…

配置文件,xml,json,yaml,我該選哪個?

文章目錄 一、核心特性對比二、性能與生態系統三、適用場景與選型建議四、替代方案與趨勢五、總結 在軟件開發中&#xff0c;配置文件格式的選擇直接影響開發效率和維護成本。XML、JSON、YAML 是目前主流的三種格式&#xff0c;但它們各有適用場景和局限性。本文將從語法特性、…

產品迭代與放棄的判斷:MVP、PMF 與 Scale Fit 的三重驗證

在創業和產品管理的世界里&#xff0c;一個永恒的難題是&#xff1a;什么時候應該繼續投入資源進行產品迭代&#xff1f;什么時候又該果斷放棄&#xff1f; 這是一個既關乎戰略方向&#xff0c;又涉及資源分配的核心命題。許多初創公司或產品團隊往往在錯誤的方向上堅持太久&a…

DAY 35 模型可視化與推理

知識點回顧&#xff1a; 三種不同的模型可視化方法&#xff1a;推薦torchinfo打印summary權重分布可視化進度條功能&#xff1a;手動和自動寫法&#xff0c;讓打印結果更加美觀推理的寫法&#xff1a;評估模式 作業&#xff1a;調整模型定義時的超參數&#xff0c;對比下效果。…

20250523-BUG-E1696:無法打開元數據文件“platform.winmd(已解決)

BUG&#xff1a;E1696&#xff1a;無法打開元數據文件“platform.winmd&#xff08;已解決&#xff09; 最近在用VisualStudio2022打開一個VisualStudio2017的C老項目后報了這個錯&#xff0c;幾經周折終于解決了&#xff0c;以下是我用的解決方法&#xff1a; 將Debug從Win32改…

Hellorobot 移動操作機器人開源實踐:HPR 模型 + 全棧資源,降低家庭機器人開發門檻

Hellorobot在DobbE框架中扮演了重要的技術支柱角色。通過其尖端的模塊化設計和高效算法優化&#xff0c;Hellorobot為家庭機器人領域注入了強大的創新動力。DobbE框架的核心技術——Home Pretrained Representations (HPR) 模型&#xff0c;得益于Hellorobot的技術支持&#xf…

onnx模型轉入rknn3399平臺上工作記錄

1.rknn虛擬環境使用時報錯問題 使用rknn17環境的報錯&#xff1a; ImportError: libdc1394.so.22: cannot open shared object file: No such file or directory 參考鏈接&#xff1a;https://blog.csdn.net/2301_80032564/article/details/142316410 創作軟連接&#xff1a; …

杰發科技AC7840——CSE硬件加密模塊使用(1)

1. 簡介 2. 功能概述 3. 簡單的代碼分析 測試第二個代碼例程 初始化隨機數 這里的CSE_CMD_RND在FuncID中體現了 CSE_SECRET_KEY在17個用戶KEY中體現 最后的讀取RNG值&#xff0c;可以看出計算結果在PRAM中。 總的來看 和示例說明一樣&#xff0c;CSE 初次使用&#xff0c;添加…

AI要掌握的知識

AI&#xff08;人工智能&#xff09;是一個跨學科的復雜領域&#xff0c;其知識體系涵蓋理論基礎、技術工具和實踐應用等多個層面。以下從核心知識模塊、技術工具、實踐方向等角度&#xff0c;詳細梳理 AI 從業者需要掌握的知識體系&#xff1a; 一、數學基礎&#xff1a;AI 的…

Python Click庫:輕松構建優雅的命令行工具

Python Click庫&#xff1a;輕松構建優雅的命令行工具 引言一、Click 適用場景二、安裝 Click三、基礎使用1. 第一個 Click 程序2. 添加位置參數3. 使用選項參數 四、高級功能1. 子命令分組&#xff08;多級命令&#xff09;2. 參數類型驗證3. 彩色終端輸出 五、實用功能示例&a…

三種常見脈沖神經網絡編碼方式解讀

速率編碼&#xff08;rate coding) 速率編碼使用輸入特征來確定尖峰頻率&#xff0c;例如將靜態輸入數據&#xff08;如 MNIST 圖像&#xff09;轉換為時間上的脈沖&#xff08;spike&#xff09;序列。它是將神經元發放脈沖的頻率與輸入值&#xff08;如像素強度&#xff09;…

Selenium 測試框架 - Python

??Selenium Python 實戰指南:從入門到進階 Selenium 是 Web 自動化測試中最受歡迎的工具之一,支持多種瀏覽器和語言。本文將從環境搭建到多瀏覽器兼容、測試框架集成、元素定位方式、常用操作、瀏覽器配置等多個方面進行詳細講解,并分享常見的最佳實踐建議。 ??一、環境…

第四十九節:圖像分割-基于深度學習的圖像分割

1. 引言 在計算機視覺領域,圖像分割(Image Segmentation)是一項基礎且關鍵的技術,其目標是將圖像劃分為多個具有特定語義的區域。隨著深度學習技術的突破,基于神經網絡的圖像分割方法在精度和效率上都實現了質的飛躍。本文將重點介紹如何利用OpenCV結合深度學習模型實現高…

【GESP】C++三級真題 luogu-B4039 [GESP202409 三級] 回文拼接

GESP三級真題&#xff0c;字符串相關題目&#xff0c;難度★★?☆☆。 題目題解詳見&#xff1a;https://www.coderli.com/gesp-3-luogu-b4039/ 【GESP】C三級真題 luogu-B4039 [GESP202409 三級] 回文拼接 | OneCoderGESP三級真題&#xff0c;字符串相關題目&#xff0c;難…

什么是深度學習中的層次分類問題?

深度學習中的層次分類問題&#xff08;Hierarchical Classification&#xff09;是指分類任務中存在類別間的層次結構&#xff0c;且模型需要根據這種層次關系進行預測的問題。與傳統的扁平分類&#xff08;Flat Classification&#xff09;不同&#xff0c;層次分類要求模型在…

黑馬點評-樂觀鎖/悲觀鎖/synchronized/@Transactional

文章目錄 全局ID生成器超賣樂觀鎖 一人一單悲觀鎖 當我們確認訂單時&#xff0c;系統需要給我們返回我們的訂單編號。這個時候就會出現兩個大問題。 1.訂單id采用數據庫里的自增的話&#xff0c;安全性降低。比如今天我的訂單是10&#xff0c;我明天的訂單是100&#xff0c;那…

python下通過wmic設置程序的優先級~~~

在開發過程中&#xff0c;經常會碰到需要設置程序優先級&#xff0c;這時候可以手動到任務管理器中調整&#xff0c;但是這多多少少有些不方便&#xff0c;那么這時候我們就可以通過subprocess調用wmic命令來實現&#xff0c;方法如下: step 1 必要的引用: import subprocess…

在Mac中使用pyenv管理Python版本:從安裝到虛擬環境的全流程指南

# 在Mac中使用pyenv管理Python版本&#xff1a;從安裝到虛擬環境的全流程指南 ## 一、為什么選擇pyenv&#xff1f; 在開發過程中&#xff0c;不同項目往往需要不同的Python版本&#xff08;如3.8 vs 3.10&#xff09;&#xff0c;而系統默認的Python環境難以滿足靈活切換的需…