六種常用設計模式

單例設計模式

單例模式指在整個系統生命周期里,保證一個類只能產生一個實例,確保該類的唯一性。

單例模式分類

單例模式可以分為懶漢式和餓漢式,兩者之間的區別在于創建實例的時間不同:

  • 懶漢式:指系統運行中,實例并不存在,只有當需要使用該實例時,才會去創建并使用實例。(這種方式要考慮線程安全)
  • 餓漢式:指系統一運行,就初始化創建實例,當需要時,直接調用即可。(本身就線程安全,沒有多線程的問題)

單例類特點

  • 構造函數和析構函數為private類型,目的禁止外部構造和析構
  • 拷貝構造和賦值運算符重載函數為private類型,目的是禁止外部拷貝和賦值,確保實例的唯一性

單例類的結構

  • 一個public的獲取指向唯一的實例對象的指針的函數GetInstance()
  • 構造函數析構函數設為private,禁止外部構造和析構
  • 拷貝構造和賦值操作符重載函數設為private類型,禁止外部拷貝和賦值,確保實例的唯一性
  • 一個private的static的指向唯一的實例對象的指針

代碼實現

//線程安全的懶漢模式
class singleClass {
public:static singleClass* getinstance(){//雙重鎖模式if (instance == nullptr){//先判斷是否為空,如果為空則進入,不為空說明已經存在實例,直接返回//進入后加鎖i_mutex.lock();if (instance == nullptr){//再判斷一次,確保不會因為加鎖期間多個線程同時進入instance = new singleClass();}i_mutex.unlock();//解鎖}return instance;}
private:static singleClass* instance;static mutex i_mutex;//鎖singleClass(){}singleClass(const singleClass& sc) {}//拷貝構造函數也需要設置為私有
};
singleClass* singleClass::instance=nullptr;
mutex singleClass::i_mutex;//類外初始化
//餓漢模式:不管用不用得到,都構造出來。本身就是線程安全的
class ehsingleClass {
public:static ehsingleClass* getinstance(){return instance;}private:static ehsingleClass* instance;//靜態成員變量必須類外初始化,只有一個ehsingleClass() {};ehsingleClass(const ehsingleClass& sc) {}//拷貝構造函數也需要設置為私有
};
ehsingleClass* ehsingleClass::instance = new ehsingleClass();
//類外定義,main開始執行前,該對象就存在了

工廠設計模式

工廠模式概念

工廠模式是一種創建型設計模式,它提供了一種封裝對象創建過程的方式,從而使得客戶端代碼與創建具體對象的過程解耦合。

工廠模式主要包含以下幾種變體:

  1. 簡單工廠模式(Simple Factory Pattern):簡單工廠模式通過一個工廠類來創建對象,客戶端通過調用工廠類的靜態方法或非靜態方法來獲取所需的對象實例。這種模式不符合開閉原則,因為每次新增產品都需要修改工廠類。

  2. 工廠方法模式(Factory Method Pattern):工廠方法模式將對象的創建委托給子類來完成。定義一個創建對象的接口,但讓子類決定實例化哪個類。這種模式遵循了開閉原則,因為可以通過添加新的子類來擴展系統功能。

  3. 抽象工廠模式(Abstract Factory Pattern):抽象工廠模式提供了一個接口,用于創建相關或依賴對象的家族,而不需要指定具體的類。它是工廠方法模式的擴展,通過定義多個工廠接口來創建一系列相關對象。

工廠模式的核心思想是將對象的創建過程封裝起來,使得客戶端代碼不需要直接依賴于具體對象的創建過程,而是依賴于工廠接口或方法來獲取所需的對象實例。這樣可以降低代碼的耦合度,提高系統的靈活性和可維護性。

工廠模式適用于以下情況:

  • 當一個類不知道它必須創建的對象的類時。
  • 當一個類希望由其子類來指定所創建的對象時。
  • 當需要將對象的創建和使用分離時,以便更好地組織代碼結構和邏輯關系。

1. 簡單工廠模式(Simple Factory Pattern)

#include <iostream>// 抽象產品類
class Product {
public:virtual void operation() = 0;virtual ~Product() {}
};// 具體產品類A
class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA: operation()" << std::endl;}
};// 具體產品類B
class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB: operation()" << std::endl;}
};// 簡單工廠類
class SimpleFactory {
public:static Product* createProduct(char type) {switch (type) {case 'A':return new ConcreteProductA();case 'B':return new ConcreteProductB();default:return nullptr;}}
};int main() {// 創建具體產品對象Product* productA = SimpleFactory::createProduct('A');Product* productB = SimpleFactory::createProduct('B');// 調用具體產品對象的方法if (productA) productA->operation();if (productB) productB->operation();// 釋放資源delete productA;delete productB;return 0;
}

2. 工廠方法模式(Factory Method Pattern)

#include <iostream>// 抽象產品類
class Product {
public:virtual void operation() = 0;virtual ~Product() {}
};// 具體產品類A
class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA: operation()" << std::endl;}
};// 具體產品類B
class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB: operation()" << std::endl;}
};// 抽象工廠類
class Factory {
public:virtual Product* createProduct() = 0;virtual ~Factory() {}
};// 具體工廠類A
class ConcreteFactoryA : public Factory {
public:Product* createProduct() override {return new ConcreteProductA();}
};// 具體工廠類B
class ConcreteFactoryB : public Factory {
public:Product* createProduct() override {return new ConcreteProductB();}
};int main() {// 創建具體工廠對象Factory* factoryA = new ConcreteFactoryA();Factory* factoryB = new ConcreteFactoryB();// 創建具體產品對象Product* productA = factoryA->createProduct();Product* productB = factoryB->createProduct();// 調用具體產品對象的方法if (productA) productA->operation();if (productB) productB->operation();// 釋放資源delete factoryA;delete factoryB;delete productA;delete productB;return 0;
}

3. 抽象工廠模式(Abstract Factory Pattern)

#include <iostream>// 抽象產品類A
class AbstractProductA {
public:virtual void operationA() = 0;virtual ~AbstractProductA() {}
};// 具體產品類A1
class ConcreteProductA1 : public AbstractProductA {
public:void operationA() override {std::cout << "ConcreteProductA1: operationA()" << std::endl;}
};// 具體產品類A2
class ConcreteProductA2 : public AbstractProductA {
public:void operationA() override {std::cout << "ConcreteProductA2: operationA()" << std::endl;}
};// 抽象產品類B
class AbstractProductB {
public:virtual void operationB() = 0;virtual ~AbstractProductB() {}
};// 具體產品類B1
class ConcreteProductB1 : public AbstractProductB {
public:void operationB() override {std::cout << "ConcreteProductB1: operationB()" << std::endl;}
};// 具體產品類B2
class ConcreteProductB2 : public AbstractProductB {
public:void operationB() override {std::cout << "ConcreteProductB2: operationB()" << std::endl;}
};// 抽象工廠類
class AbstractFactory {
public:virtual AbstractProductA* createProductA() = 0;virtual AbstractProductB* createProductB() = 0;virtual ~AbstractFactory() {}
};// 具體工廠類1
class ConcreteFactory1 : public AbstractFactory {
public:AbstractProductA* createProductA() override {return new ConcreteProductA1();}AbstractProductB* createProductB() override {return new ConcreteProductB1();}
};// 具體工廠類2
class ConcreteFactory2 : public AbstractFactory {
public:AbstractProductA* createProductA() override {return new ConcreteProductA2();}AbstractProductB* createProductB() override {return new ConcreteProductB2();}
};int main() {// 創建具體工廠對象AbstractFactory* factory1 = new ConcreteFactory1();AbstractFactory* factory2 = new ConcreteFactory2();// 創建具體產品對象AbstractProductA* productA1 = factory1->createProductA();AbstractProductB* productB1 = factory1->createProductB();AbstractProductA* productA2 = factory2->createProductA();AbstractProductB* productB2 = factory2->createProductB();// 調用具體產品對象的方法if (productA1) productA1->operationA();if (productB1) productB1->operationB();if (productA2) productA2->operationA();if (productB2) productB2->operationB();// 釋放資源delete factory1;delete factory2;delete productA1;delete productB1;delete productA2;delete productB2;return 0;
}

抽象工廠模式(Abstract Factory Pattern)和工廠方法模式(Factory Method Pattern)都屬于工廠模式的范疇,但它們之間有一些關鍵區別:

  1. 目的

    • 抽象工廠模式旨在提供一個接口,用于創建一系列相關或依賴對象的家族,而不需要指定具體的類。
    • 工廠方法模式旨在將對象的創建委托給子類來完成。它定義一個創建對象的接口,但讓子類決定實例化哪個類。
  2. 結構

    • 抽象工廠模式通常由一個抽象工廠接口和多個具體工廠類組成。每個具體工廠類負責創建一個產品家族的產品。
    • 工廠方法模式通常由一個抽象產品類和一個抽象工廠類組成。抽象工廠類定義了創建產品的方法,具體工廠類負責實現這些方法來創建具體產品。
  3. 擴展

    • 抽象工廠模式通過添加新的具體工廠類來擴展系統,每個具體工廠類負責創建一個產品家族的產品。
    • 工廠方法模式通過添加新的具體工廠類或擴展現有的抽象工廠類來擴展系統,每個具體工廠類負責創建一個具體產品。
  4. 關系

    • 抽象工廠模式通常與工廠方法模式結合使用,一個抽象工廠類中可以包含多個工廠方法,每個工廠方法負責創建一個具體產品。
    • 工廠方法模式是抽象工廠模式的一個特例,它將抽象工廠類中的工廠方法設計成抽象的,然后由具體子類來實現。

觀察者模式

觀察者模式(Observer Pattern)

觀察者模式(Observer Pattern)是一種行為設計模式,它定義了一種一對多的依賴關系,讓多個觀察者對象監聽一個主題對象,當主題對象的狀態發生變化時,所有依賴于它的觀察者都會收到通知并自動更新。

在觀察者模式中,有三個關鍵角色:

  1. Subject(主題):也稱為被觀察者或可觀察對象,它是一個抽象類或接口,定義了被觀察者需要實現的方法。主題對象維護一個觀察者列表,并提供方法來注冊、移除和通知觀察者。

  2. Observer(觀察者):也稱為訂閱者或監聽者,它是一個抽象類或接口,定義了觀察者需要實現的方法。觀察者對象通過訂閱主題對象來接收狀態變化的通知,并執行相應的操作。

  3. ConcreteSubject(具體主題):是主題對象的具體實現類,它繼承或實現了主題接口,并維護了一個狀態變量。當狀態變量發生變化時,具體主題對象會通知所有注冊的觀察者。

  4. ConcreteObserver(具體觀察者):是觀察者對象的具體實現類,它繼承或實現了觀察者接口,并定義了在接收到主題對象通知時所需要執行的操作。

觀察者模式的優點包括:

  • 松耦合:主題對象和觀察者對象之間是松耦合的,它們之間沒有直接的依賴關系,可以獨立地進行修改和擴展。
  • 可重用性:可以在不同的主題和觀察者之間進行重復使用,使得代碼更加靈活和可維護。
  • 多態性:可以通過繼承和接口實現多態性,從而可以根據需要定義不同類型的主題和觀察者。

觀察者模式適用于以下情況:

  • 當一個對象的狀態變化需要通知其他對象,并且不知道有多少個對象需要通知時。
  • 當一個對象的狀態變化需要通知其他對象,但不希望這些對象與之耦合時。
  • 當一個對象的狀態變化會導致其他對象的行為發生變化時。

工作流程:

觀察者模式的工作流程通常涉及以下幾個步驟:

  1. 定義主題接口:首先,需要定義一個主題接口或抽象類,其中包含了注冊、移除和通知觀察者的方法。這個接口或抽象類定義了主題對象的基本行為。

  2. 定義觀察者接口:然后,需要定義一個觀察者接口或抽象類,其中包含了接收通知并進行相應操作的方法。這個接口或抽象類定義了觀察者的基本行為。

  3. 創建具體主題類:接著,創建一個具體主題類,實現主題接口,并維護一個觀察者列表。具體主題類通常包含一個狀態變量,當狀態變化時會通知所有注冊的觀察者。

  4. 創建具體觀察者類:然后,創建一個或多個具體觀察者類,實現觀察者接口,并定義在接收到主題對象通知時所需要執行的操作。每個具體觀察者類通常包含一個指向具體主題對象的引用。

  5. 注冊觀察者:在需要訂閱主題對象的觀察者處,將具體觀察者對象注冊到具體主題對象的觀察者列表中。

  6. 狀態變化通知:當具體主題對象的狀態發生變化時,調用通知方法,遍歷觀察者列表,并依次通知每個觀察者對象。

  7. 觀察者響應:每個觀察者對象在接收到通知后,會執行相應的操作,根據具體業務需求進行處理。

  8. 取消注冊觀察者(可選):如果觀察者不再對主題對象的狀態變化感興趣,可以取消注冊觀察者,將其從觀察者列表中移除

代碼實現

#include <iostream>
#include <vector>// 定義觀察者接口
class Observer {
public:virtual void update(int data) = 0;virtual ~Observer() {}
};// 定義具體觀察者類
class ConcreteObserver : public Observer {
public:void update(int data) override {std::cout << "ConcreteObserver received update: " << data << std::endl;}
};// 定義主題接口
class Subject {
public:virtual void attach(Observer* observer) = 0;virtual void detach(Observer* observer) = 0;virtual void notify(int data) = 0;virtual ~Subject() {}
};// 定義具體主題類
class ConcreteSubject : public Subject {
public:void attach(Observer* observer) override {observers.push_back(observer);}void detach(Observer* observer) override {auto it = std::find(observers.begin(), observers.end(), observer);if (it != observers.end()) {observers.erase(it);}}void notify(int data) override {for (Observer* observer : observers) {observer->update(data);}}private:std::vector<Observer*> observers;
};int main() {// 創建具體主題對象ConcreteSubject subject;// 創建具體觀察者對象ConcreteObserver observer1;ConcreteObserver observer2;// 注冊觀察者subject.attach(&observer1);subject.attach(&observer2);// 發送通知subject.notify(123);// 移除觀察者subject.detach(&observer1);// 再次發送通知subject.notify(456);return 0;
}

代理模式

代理模式(Proxy Pattern)

代理模式(Proxy Pattern)是一種結構型設計模式,它允許你提供一個代理對象來控制對其他對象的訪問。代理對象通常充當客戶端和目標對象之間的中間人,客戶端通過代理對象間接訪問目標對象,從而可以在訪問過程中添加額外的功能,如延遲加載、訪問控制、緩存等。

在代理模式中,通常有三個角色:

  1. Subject(抽象主題):定義了目標對象和代理對象共同實現的接口,它可以是抽象類或接口。抽象主題可以是真實主題和代理對象的共同接口,也可以是真實主題的接口。

  2. RealSubject(真實主題):定義了真實對象的具體實現,是代理模式中的核心對象。客戶端最終想要訪問的對象就是真實主題。

  3. Proxy(代理):實現了抽象主題接口,并維護一個指向真實主題的引用。代理對象在執行目標對象方法的同時,可以在方法執行前后添加額外的邏輯。

代理模式的優點包括:

  • 控制訪問:可以通過代理對象來控制對真實對象的訪問,如權限控制、審計等。
  • 增加功能:可以在不改變目標對象的前提下,通過代理對象為目標對象增加額外的功能,如緩存、延遲加載、日志記錄等。
  • 保護目標對象:可以對真實對象進行保護,防止客戶端直接訪問,從而提高系統的安全性。

代理模式適用于以下情況:

  • 當需要在訪問一個對象時添加額外的功能,但又不想修改原有的代碼時。
  • 當需要對訪問進行控制和保護時,如權限控制、審計等。
  • 當需要在訪問一個遠程對象或昂貴對象時進行性能優化,如延遲加載、緩存等。

代碼實現

#include <iostream>// 定義抽象主題接口
class Subject {
public:virtual void request() = 0;virtual ~Subject() {}
};// 定義具體主題類
class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject: Handling request." << std::endl;}
};// 定義代理類
class Proxy : public Subject {
public:Proxy(Subject* realSubject) : realSubject(realSubject) {}void request() override {if (checkAccess()) {realSubject->request();logAccess();} else {std::cout << "Proxy: Access denied." << std::endl;}}private:Subject* realSubject;bool checkAccess() {// 檢查訪問權限的邏輯std::cout << "Proxy: Checking access..." << std::endl;return true; // 簡單起見,這里直接返回 true}void logAccess() {// 記錄訪問日志的邏輯std::cout << "Proxy: Logging access..." << std::endl;}
};int main() {// 創建真實主題對象RealSubject* realSubject = new RealSubject();// 創建代理對象,并將真實主題對象傳入代理對象的構造函數中Proxy* proxy = new Proxy(realSubject);// 通過代理對象訪問真實主題對象的方法proxy->request();// 釋放資源delete proxy;delete realSubject;return 0;
}

裝飾器模式

裝飾器模式(Decorator Pattern)

裝飾器模式(Decorator Pattern)是一種結構型設計模式,它允許你通過將對象放入包裝器中來動態地擴展其行為。裝飾器模式提供了一種靈活的方式來添加功能,而無需修改現有的代碼。

在裝飾器模式中,有四個關鍵角色:

  1. Component(組件):是一個抽象類或者接口,定義了被裝飾對象和裝飾器共同遵循的協議或契約。它可以是抽象類或接口,定義了具體組件和裝飾器必須實現的操作。

  2. Concrete Component(具體組件):是實現了組件接口的具體對象。具體組件是被裝飾的對象,它定義了基本行為,可以通過裝飾器來擴展。

  3. Decorator(裝飾器):是一個抽象類,實現了組件接口,并包含一個對組件對象的引用。裝飾器可以根據需要對組件對象進行包裝,以擴展其行為。

  4. Concrete Decorator(具體裝飾器):是實現了裝飾器接口的具體對象。具體裝飾器包裝了具體組件對象,并在其基礎上添加額外的行為或功能。

裝飾器模式的工作流程:

  1. 定義組件接口:首先,定義一個組件接口或抽象類,它聲明了被裝飾對象和裝飾器共同遵循的協議或契約。組件接口通常包含一個或多個方法,用于定義組件的基本行為。

  2. 實現具體組件類:根據組件接口,創建一個具體的組件類,實現組件接口中定義的方法。具體組件類是被裝飾的對象,它定義了基本行為,是裝飾器模式的核心。

  3. 創建裝飾器抽象類:定義一個裝飾器抽象類,它實現了組件接口,并包含一個對組件對象的引用。裝飾器抽象類提供了一個統一的接口,用于包裝組件對象并在其基礎上添加額外的功能。

  4. 實現具體裝飾器類:根據裝飾器抽象類,創建具體的裝飾器類,實現裝飾器抽象類中定義的方法。具體裝飾器類可以根據需要在組件對象的基礎上添加額外的行為或功能,從而擴展組件的功能。

  5. 創建裝飾器鏈:根據業務需求,可以將多個裝飾器對象按照一定的順序組合成一個裝飾器鏈。裝飾器鏈中的每個裝飾器對象都包裝了一個組件對象,并可以在其基礎上添加額外的功能。

  6. 使用裝飾器模式:在客戶端代碼中,根據需要創建具體組件對象,并根據業務需求創建相應的裝飾器對象,并將其按照一定的順序組合成裝飾器鏈。然后通過調用裝飾器鏈的方法來執行操作,裝飾器鏈會根據其包裝的組件對象的類型以及裝飾器對象的順序依次執行相應的功能。

代碼實現:

#include <iostream>// 抽象組件
class Component {
public:virtual void operation() = 0;virtual ~Component() {}
};// 具體組件
class ConcreteComponent : public Component {
public:void operation() override {std::cout << "ConcreteComponent: operation()" << std::endl;}
};// 裝飾器抽象類
class Decorator {
public:Decorator(Component* component) : component(component) {}void operation()  {if (component != nullptr) {component->operation();}}protected:Component* component;
};// 具體裝飾器A
class ConcreteDecoratorA : public Decorator {
public:ConcreteDecoratorA(Component* component) : Decorator(component) {}void operation() override {Decorator::operation();addBehavior();}void addBehavior() {std::cout << "ConcreteDecoratorA: addBehavior()" << std::endl;}
};// 具體裝飾器B
class ConcreteDecoratorB : public Decorator {
public:ConcreteDecoratorB(Component* component) : Decorator(component) {}void operation() override {Decorator::operation();addBehavior();}void addBehavior() {std::cout << "ConcreteDecoratorB: addBehavior()" << std::endl;}
};int main() {// 創建具體組件對象Component* component = new ConcreteComponent();// 創建具體裝飾器A,并包裝具體組件對象Decorator* decoratorA = new ConcreteDecoratorA(component);// 創建具體裝飾器B,并包裝具體裝飾器ADecorator* decoratorB = new ConcreteDecoratorB(decoratorA);// 執行操作decoratorB->operation();// 釋放資源delete decoratorB;delete decoratorA;delete component;return 0;
}

策略模式

策略模式(Strategy Pattern)

策略模式(Strategy Pattern)是一種行為設計模式,它定義了一系列算法,并使得這些算法可以相互替換,使得客戶端在使用算法時可以獨立于其具體實現。策略模式將算法的定義、使用和實現分離開來,使得每個算法可以獨立變化而不影響其他部分。

在策略模式中,有三個關鍵角色:

  1. Context(上下文):上下文是策略模式的核心類,它包含了一個策略接口的引用,并在運行時根據具體的情況選擇合適的算法來執行。上下文類通常提供一個設置策略的方法,以及一個執行策略的方法。

  2. Strategy(策略):策略是一個接口或抽象類,它定義了一系列算法的共同接口。具體的策略類實現了策略接口,并提供了具體的算法實現。

  3. ConcreteStrategy(具體策略):具體策略是策略模式的具體實現類,它實現了策略接口,并提供了具體的算法實現。

策略模式的優點包括:

  • 分離算法:將算法的定義、使用和實現分離開來,使得每個算法可以獨立變化而不影響其他部分。
  • 擴展性:增加新的算法非常方便,只需要實現新的策略類,并在上下文中設置即可。
  • 復用性:策略模式使得算法可以在不同的上下文中共享和重復使用。

策略模式適用于以下情況:

  • 當一個類有多種行為,且需要在運行時根據具體情況選擇合適的行為時。
  • 當一個類的行為可以通過組合不同的算法來實現,并且這些算法可以相互替換時。
  • 當一個類的行為在不同的上下文中需要不同的實現時。

工作流程

策略模式的工作流程可以描述為以下幾個步驟:

  1. 定義策略接口(Strategy Interface):首先,定義一個策略接口,該接口包含了需要實現的算法方法。這個接口可以是一個抽象類或者一個純虛函數接口,具體取決于編程語言和具體需求。

  2. 實現具體策略類(Concrete Strategy Classes):接下來,為每個具體的算法實現類編寫具體的策略類。這些類實現了策略接口,并提供了具體的算法邏輯。

  3. 創建上下文類(Context Class):定義一個上下文類,它包含了一個指向策略接口的引用。上下文類負責在運行時根據具體的情況選擇合適的策略,并將任務委托給策略對象。

  4. 設置和切換策略:在上下文類中提供設置和切換策略的方法,使得客戶端可以根據需要選擇不同的策略。

  5. 客戶端調用:客戶端創建上下文對象,并根據具體的需求選擇合適的策略,并調用相應的方法執行算法。

代碼實現

#include <iostream>// 定義策略接口
class Strategy {
public:virtual void execute() = 0;virtual ~Strategy() {}
};// 實現具體策略類
class ConcreteStrategyA : public Strategy {
public:void execute() override {std::cout << "Executing strategy A" << std::endl;}
};class ConcreteStrategyB : public Strategy {
public:void execute() override {std::cout << "Executing strategy B" << std::endl;}
};// 創建上下文類
class Context {
public:Context(Strategy* strategy) : strategy(strategy) {}// 設置和切換策略void setStrategy(Strategy* newStrategy) {strategy = newStrategy;}// 調用策略方法void executeStrategy() {strategy->execute();}private:Strategy* strategy;
};int main() {// 創建具體策略對象ConcreteStrategyA strategyA;ConcreteStrategyB strategyB;// 創建上下文對象,并設置初始策略Context context(&strategyA);// 執行初始策略context.executeStrategy(); // 輸出 "Executing strategy A"// 切換策略并執行context.setStrategy(&strategyB);context.executeStrategy(); // 輸出 "Executing strategy B"return 0;
}

在這個示例中,Strategy 是策略接口,定義了執行策略的方法。ConcreteStrategyAConcreteStrategyB 是具體策略類,分別實現了策略接口中的方法,即具體的算法實現。Context 是上下文類,它包含一個策略接口的引用,并提供了設置策略和執行策略的方法。在 main 函數中,創建了具體策略對象和上下文對象,并使用上下文對象執行了具體的策略。

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

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

相關文章

SpringBootWeb 篇-深入了解 Mybatis 刪除、新增、更新、查詢的基礎操作與 SQL 預編譯解決 SQL 注入問題

&#x1f525;博客主頁&#xff1a; 【小扳_-CSDN博客】 ?感謝大家點贊&#x1f44d;收藏?評論? 文章目錄 1.0 Mybatis 的基礎操作 2.0 基礎操作 - 環境準備 3.0 基礎操作 - 刪除操作 3.1 SQL 預編譯 3.2 SQL 預編譯的優勢 3.3 參數占位符 4.0 基礎操作 - 新增 4.1 主鍵返回…

Python圖像處理:從基礎到高級的全方位指南

目錄 第一部分&#xff1a;Python圖像處理基礎 1.1 圖像處理概念 1.2 Python圖像處理常用庫 1.3 實戰案例&#xff1a;圖像顯示與保存 1.4 注意事項 第二部分&#xff1a;Python圖像處理高級技巧 2.1 圖像變換 2.2 圖像增強 2.3 圖像復原 第三部分&#xff1a;Python…

esp32s3中ap與sta模式的wps配對問題

無線路由器中的WPS是Wi-Fi Protected Setup的簡稱&#xff0c;中文翻譯為Wi-Fi安全防護設置&#xff0c;它是由Wi-Fi安全聯盟推出的一種無線加密認證方式。主要是為了簡化無線局域網的安裝及安全性能配置工作&#xff0c;通過這種設置&#xff0c;讓無線連接更加方便和安全。省…

20232802 黃千里 2023-2024-2 《網絡攻防實踐》實踐十一報告

20232802 2023-2024-2 《網絡攻防實踐》實踐十一報告 1.實踐過程 1.1web瀏覽器滲透攻擊 攻擊機&#xff1a;kali172.20.10.10靶機&#xff1a;win2k172.20.10.3 首先在kali中啟動msfconsole 輸入命令search MS06-014&#xff0c;搜索滲透攻擊模塊 輸入use exploit/window…

終于讓我找到了,你也可以學會的人工智能-機器學習教程

給大家分享一套非常棒的python機器學習課程——《AI小天才&#xff1a;讓小學生輕松掌握機器學習》&#xff0c;2024年5月完結新課&#xff0c;提供配套的代碼筆記軟件包下載&#xff01;學完本課程&#xff0c;可以輕松掌握機器學習的全面應用&#xff0c;復雜特征工程&#x…

C# 跨線程訪問UI組件,serialPort1串口接收數據

在Windows應用程序&#xff08;例如WinForms或WPF&#xff09;中&#xff0c;UI組件&#xff08;如按鈕、文本框等&#xff09;都在主線程&#xff08;也稱為UI線程&#xff09;上運行。當你在一個非UI線程&#xff08;例如&#xff0c;一個后臺線程或者網絡請求線程&#xff0…

關于新配置的adb,設備管理器找不到此設備問題

上面頁面中一開始沒有找到此android設備&#xff0c; 可能是因為我重新配置的adb和設備驅動&#xff0c; 只把adb配置了環境變量&#xff0c;驅動沒有更新到電腦中&#xff0c; 點擊添加驅動&#xff0c; 選擇路徑&#xff0c;我安裝時都放在了SDK下面&#xff0c;可以嘗試…

SpringBoot 實現 RAS+AES 自動接口解密

一、講個事故 接口安全老生常談了 過年之前做了過一款飛機大戰的H5小游戲&#xff0c;里面無限模式-需要保存用戶的積分&#xff0c;因為使用的Body傳參&#xff0c;參數是可見的。 為了接口安全我&#xff0c;我和前端約定了傳遞參數是&#xff1a;用戶無限模式的積分“我們…

HTML靜態網頁成品作業(HTML+CSS)——魅族商城首頁網頁(1個頁面)

&#x1f389;不定期分享源碼&#xff0c;關注不丟失哦 文章目錄 一、作品介紹二、作品演示三、代碼目錄四、網站代碼HTML部分代碼 五、源碼獲取 一、作品介紹 &#x1f3f7;?本套采用HTMLCSS&#xff0c;未使用Javacsript代碼&#xff0c;共有1個頁面。 二、作品演示 三、代…

基于Python+OpenCV卷積神經網絡的字符識別

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 字符識別是計算機視覺和模式識別領域的一個重要應用&#xff0c;它在文檔數字化、車牌識別、驗…

gpt-4o考場安排

說明 &#xff1a;經過多次交互&#xff0c;前后花了幾個小時&#xff0c;總算完成了基本功能。如果做到按不同層次分配考場&#xff0c;一鍵出打印結果就完美了。如果不想看中間“艱苦”的過程&#xff0c;請直接跳到“最后結果”及“食用方法”。中間過程還省略了一部分交互&…

Android-多個tv_item_[i] 點擊事件簡寫

private TextView[] tvConstellations new TextView[12];//獲取當前id元素并在其點擊的時候修改其顏色 for (int i 0; i < 12; i) {int resId getResources().getIdentifier("tv_constellation_" (i1), "id", getPackageName());tvConstellations[i…

神經網絡與深度學習 課程復習總結

神經網絡的發展歷史 第一代神經網絡&#xff08;1958~1969&#xff09; MCP模型&#xff08;1943年&#xff09;&#xff1a;麥卡洛克和皮茨提出了第一個人工神經元模型&#xff0c;簡化為輸入信號線性加權、求和、非線性激活&#xff08;閾值法&#xff09;。感知器&#xf…

鴻蒙開發 組件之間的傳值

1.Prop&#xff1a;父組件傳遞給子組件&#xff0c;單向傳遞&#xff0c;子組件改變值&#xff0c;父組件UI不更新。 引入子組件 并賦值&#xff0c;子組件用Prop 接收 import headerView from ../../common/bean/BaseNavHeaderView headerView({titlestr:添加地址,isback…

go slice 擴容

擴容 slice 會遷移到新的內存位置&#xff0c;新底層數組的長度也會增加&#xff0c;這樣就可以放置新增的元素。同時&#xff0c;為了應對未來可能再次發生的 append 操作&#xff0c;新的底層數組的長度&#xff0c;也就是新 slice 的容量是留了一定的 buffer 的。否則&…

【C++】STL快速入門基礎

文章目錄 STL&#xff08;Standard Template Library&#xff09;1、一般介紹2、STL的六大組件2.1、STL容器2.2、STL迭代器2.3、相關容器的函數vectorpairstringqueuepriority_queuestackdequeset, map, multiset, multimapunordered_set, unordered_map, unordered_multiset, …

LabVIEW2022安裝教程指南【附安裝包】

文章目錄 前言一、安裝指南1、軟件包獲取 二、安裝步驟總結 前言 LabVIEW是一種程序開發環境&#xff0c;提供一種圖形化編程方法&#xff0c;可可視化應用程序的各個方面&#xff0c;包括硬件配置、測量數據和調試&#xff0c;同時可以通過FPGA數學和分析選板中的NI浮點庫鏈接…

有趣的css - 兩個圓形加載效果

大家好&#xff0c;我是 Just&#xff0c;這里是「設計師工作日常」&#xff0c;今天分享的是一款小清新的加載動畫&#xff0c;適用于 app 列表加載&#xff0c;頁面加載或者彈層內容延遲加載等場景。 最新文章通過公眾號「設計師工作日常」發布。 目錄 整體效果核心代碼html…

AWS安全性身份和合規性之Amazon Macie

Amazon Macie是一項數據安全和數據隱私服務&#xff0c;它利用機器學習&#xff08;ML&#xff09;和模式匹配來發現和保護敏感數據。可幫助客戶發現、分類和保護其敏感數據&#xff0c;以及監控其數據存儲庫的安全性。 應用場景&#xff1a; 敏感數據發現 一家金融服務公司…

20年交易老兵悟出的寶貴經驗,做到這10點或許你也能躺著賺錢

交易要靠親身體驗來真正獲得發展&#xff0c;在正確引導下&#xff0c;我們就不會把時間和精力浪費在彎路上。交易之技易學&#xff0c;實難在心態與思考。接下來&#xff0c;我將與您分享一位交易了20年的老兵所積累的10條珍貴經驗。 Nial Fuller,一個交易了接近20年的市場“老…