《C++设计模式》策略模式
文章目录
- 1、引言
- 1.1 什么是策略模式
- 1.2 策略模式的应用场景
- 1.3 本文结构概览
- 2、策略模式的基本概念
- 2.1 定义与结构
- 2.2 核心角色解析
- 2.2.1 策略接口(Strategy)
- 2.2.2 具体策略实现(ConcreteStrategy)
- 2.2.3 上下文(Context)
- 3、C++中的策略模式实现
- 3.1 示例场景设定
- 3.2 策略接口定义
- 3.3 具体策略实现
- 3.3.1 策略A实现:信用卡支付
- 3.3.2 策略B实现:现金支付
- 3.4 上下文类设计
- 3.5 完整代码示例
- 4、策略模式的优点与缺点
- 4.1 优点
- 4.1.1 算法自由切换
- 4.1.2 开闭原则支持
- 4.1.3 简化单元测试
- 4.2 缺点
- 4.2.1 策略类数量膨胀
- 4.2.2 客户端需要了解策略接口
- 5、策略模式的应用实例
- 5.1 电商平台的促销策略
- 5.2 游戏中的AI行为选择
- 5.3 图像处理中的滤镜选择
- 6、策略模式与其他设计模式的比较
- 6.1 与状态模式的对比
- 6.2 与模板方法模式的对比
- 6.3 与装饰者模式的对比
- 7、高级话题与最佳实践
- 7.1 使用智能指针管理策略对象
- 7.2 策略工厂模式简化策略创建
- 7.3 线程安全考虑
- 8、总结
- 8.1 策略模式的核心价值
- 8.2 何时使用策略模式
- 8.3 后续学习资源推荐
- 9、参考文献与进一步阅读
- 9.1 相关书籍推荐
1、引言
1.1 什么是策略模式
策略模式(Strategy Pattern) 是一种行为型设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以互换。策略模式使得算法可以独立于使用它的客户端而变化。策略模式让算法的变化 独立 于使用算法的客户。
在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式,因为算法或行为是通过其上下文(Context)来选择的。
简单来说,策略模式就是定义了一系列的算法,并将每一个算法封装起来,使它们可以相互替换。策略模式使得算法可独立于使用它的客户而变化,即算法本身和使用算法的客户端代码是解耦的。
1.2 策略模式的应用场景
策略模式在软件开发中有着广泛的应用场景,包括但不限于以下几种情况:
(1)多种算法的实现:当存在多种算法,而这些算法的实现又需要频繁地更换或扩展时,可以考虑使用策略模式。通过定义不同的策略类来实现不同的算法,客户端可以根据需要选择具体的策略。
(2)条件分支语句的替代:在程序中,如果存在大量的条件分支语句(如if-else或switch-case),并且这些条件分支语句的实现逻辑比较复杂或容易变化时,可以考虑使用策略模式来替代这些条件分支语句。通过定义不同的策略类来实现不同的分支逻辑,客户端可以根据条件选择具体的策略。
(3)算法与数据结构的分离:在某些情况下,算法和数据结构是紧密相关的,但有时候我们可能需要将算法与数据结构进行分离,以便能够独立地修改或扩展它们。这时,可以使用策略模式来将算法封装成独立的策略类,从而实现算法与数据结构的分离。
(4)可配置的行为:在某些系统中,某些行为可能需要根据配置或用户的选择来改变。这时,可以使用策略模式来定义不同的策略类,并根据配置或用户的选择来选择具体的策略。
1.3 本文结构概览
本文旨在详细介绍C++中的策略模式,包括其基本概念、实现方法、优缺点以及应用场景等方面。文章将分为以下几个部分:
引言:介绍策略模式的基本概念、应用场景以及本文的结构概览。
策略模式的基本概念:详细解释策略模式的定义、结构以及核心角色。
C++中的策略模式实现:通过具体的代码示例来展示如何在C++中实现策略模式。
策略模式的优缺点:分析策略模式的优点和缺点,以便更好地理解其适用场景和限制。
策略模式的应用实例:介绍一些实际项目中应用策略模式的例子,以便读者更好地理解其应用价值。
总结与展望:总结本文的主要内容,并对策略模式的发展和应用前景进行展望。
希望本文能够帮助读者深入理解C++中的策略模式,并能够在实际项目中灵活运用该模式来解决实际问题。
2、策略模式的基本概念
2.1 定义与结构
策略模式(Strategy Pattern),又称为政策模式(Policy),是一种对象行为型模式。其定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
从软件设计角度看,策略模式在一个任务中,将算法部分封装成独立的接口,和任务分离,以便可以动态选用不同算法。策略模式使得可以定义新的算法,而不引起任务本身的代码变动。这里的算法可以是数学上的算法,也可以是一个处理具体问题的方案。
2.2 核心角色解析
策略模式通常包含以下三个核心角色:
2.2.1 策略接口(Strategy)
定义:策略接口定义了一组算法或行为的公共接口,所有具体策略类都需要实现这个接口。这个接口的实现各不相同,每个实现对应一种具体的算法或行为。
作用:为所支持的算法声明了抽象方法,是所有策略类的父类。它可以是抽象类或具体类,也可以是接口。环境类通过策略接口中声明的方法在运行时调用具体策略类中实现的算法。
2.2.2 具体策略实现(ConcreteStrategy)
定义:具体策略类实现了策略接口中声明的算法。
作用:在运行时,具体策略类将覆盖在环境类中定义的策略接口对象,使用一种具体的算法实现某个业务功能。
2.2.3 上下文(Context)
定义:上下文是使用算法的角色,它在解决某个问题(即实现某个功能)时可以采用多种策略。
作用:
封装了具体策略的执行逻辑,提供给客户端使用的接口。
维持一个对策略接口的引用实例,用于定义所采用的策略。
可以在运行时动态地更换策略,从而改变算法的行为。上下文对象不需要了解算法的细节,只需调用策略接口即可。
通过以上三个角色的协同工作,策略模式实现了算法的灵活切换和扩展,提高了代码的可维护性和复用性。
3、C++中的策略模式实现
3.1 示例场景设定
为了演示C++中的策略模式,我们设定一个简单的支付系统场景。在这个系统中,用户可以选择不同的支付方式来完成支付,如信用卡支付、现金支付和支付宝支付。每种支付方式对应一个具体的策略,而支付系统则作为上下文类,根据用户的选择来执行相应的支付策略。
3.2 策略接口定义
首先,我们定义一个策略接口PaymentStrategy,它包含一个纯虚函数pay,用于执行支付操作。
#include <iostream>
#include <memory>// 策略接口
class PaymentStrategy {
public:virtual ~PaymentStrategy() = default;virtual void pay(double amount) const = 0;
};
3.3 具体策略实现
接下来,我们实现三个具体的支付策略:信用卡支付CreditCardPayment、现金支付CashPayment和支付宝支付AlipayPayment。
3.3.1 策略A实现:信用卡支付
// 信用卡支付策略
class CreditCardPayment : public PaymentStrategy {
public:void pay(double amount) const override {std::cout << "Paid " << amount << " using Credit Card." << std::endl;}
};
3.3.2 策略B实现:现金支付
// 现金支付策略
class CashPayment : public PaymentStrategy {
public:void pay(double amount) const override {std::cout << "Paid " << amount << " using Cash." << std::endl;}
};
(注:为了简洁,这里只展示了两个具体策略的实现,支付宝支付的实现方式类似,可以作为练习留给读者。)
3.4 上下文类设计
上下文类PaymentContext持有一个指向PaymentStrategy的指针(或智能指针),用于在运行时选择具体的支付策略。
// 上下文类
class PaymentContext {
private:std::unique_ptr<PaymentStrategy> strategy;public:PaymentContext(std::unique_ptr<PaymentStrategy> strategy): strategy(std::move(strategy)) {}void setStrategy(std::unique_ptr<PaymentStrategy> newStrategy) {strategy = std::move(newStrategy);}void pay(double amount) const {strategy->pay(amount);}
};
3.5 完整代码示例
下面是一个完整的代码示例,展示了如何在C++中使用策略模式来实现支付系统。
#include <iostream>
#include <memory>// 策略接口
class PaymentStrategy {
public:virtual ~PaymentStrategy() = default;virtual void pay(double amount) const = 0;
};// 信用卡支付策略
class CreditCardPayment : public PaymentStrategy {
public:void pay(double amount) const override {std::cout << "Paid " << amount << " using Credit Card." << std::endl;}
};// 现金支付策略
class CashPayment : public PaymentStrategy {
public:void pay(double amount) const override {std::cout << "Paid " << amount << " using Cash." << std::endl;}
};// 上下文类
class PaymentContext {
private:std::unique_ptr<PaymentStrategy> strategy;public:PaymentContext(std::unique_ptr<PaymentStrategy> strategy): strategy(std::move(strategy)) {}void setStrategy(std::unique_ptr<PaymentStrategy> newStrategy) {strategy = std::move(newStrategy);}void pay(double amount) const {strategy->pay(amount);}
};int main() {// 创建具体的支付策略对象auto creditCard = std::make_unique<CreditCardPayment>();auto cash = std::make_unique<CashPayment>();// 创建上下文对象,并设置初始的支付策略为信用卡支付PaymentContext context(std::move(creditCard));// 执行支付操作context.pay(100.0); // 输出: Paid 100 using Credit Card.// 动态更改支付策略为现金支付context.setStrategy(std::move(cash));// 再次执行支付操作context.pay(200.0); // 输出: Paid 200 using Cash.return 0;
}
在这个示例中,我们首先定义了策略接口PaymentStrategy,然后实现了两个具体的支付策略CreditCardPayment和CashPayment。接着,我们设计了上下文类PaymentContext,它持有一个指向PaymentStrategy的智能指针,用于在运行时选择具体的支付策略。最后,在main函数中,我们演示了如何创建具体的支付策略对象、设置上下文对象的支付策略,并执行支付操作。
4、策略模式的优点与缺点
4.1 优点
4.1.1 算法自由切换
策略模式使得算法可以独立于使用它的客户端而变化。这意味着客户端可以在运行时根据需要动态地选择不同的算法,而无需修改客户端的代码。这种灵活性有助于在不影响其他部分的情况下对系统进行扩展和修改。
4.1.2 开闭原则支持
策略模式遵循开闭原则,即对扩展开放,对修改关闭。通过增加新的策略类而不是修改已有的类来实现功能的扩展,这使得系统更加易于维护和扩展。
4.1.3 简化单元测试
由于策略模式将算法封装在独立的类中,因此可以针对每个策略类进行单独的单元测试。这有助于确保每个算法的正确性,并降低整体系统的测试复杂度。
4.2 缺点
4.2.1 策略类数量膨胀
当系统中存在大量的算法或行为时,使用策略模式可能会导致策略类的数量急剧增加。这会增加系统的复杂性和维护成本,因为需要管理大量的类和接口。
4.2.2 客户端需要了解策略接口
在使用策略模式时,客户端需要了解并选择合适的策略类。这要求客户端具有一定的了解和判断能力,以便在运行时选择最合适的算法或行为。如果客户端对策略接口的了解不足,可能会导致选择错误的策略类,从而影响系统的正确性和性能。
5、策略模式的应用实例
5.1 电商平台的促销策略
在电商平台中,促销策略是吸引用户、提高转化率的重要手段。传统的促销策略往往依赖于经验和直觉,缺乏数据支撑和精准度。随着大数据和人工智能技术的快速发展,电商促销策略也迎来了新的变革。通过策略模式,电商平台可以根据用户行为、商品属性、市场趋势等数据,构建更精准、更有效的促销策略。例如,根据用户的浏览历史、购买记录等信息,推荐个性化的商品和促销活动;或者通过分析用户对不同促销活动的响应情况,优化促销活动的时间、力度和内容。
5.2 游戏中的AI行为选择
在策略游戏中,AI的行为选择对于游戏的平衡性和趣味性至关重要。通过策略模式,游戏开发者可以为AI设计多种不同的行为策略,并在游戏运行时根据战局情况动态选择最合适的策略。例如,在战斗场景中,AI可以根据敌人的数量和类型、自身的资源和能力等因素,选择进攻、防御或撤退等不同的行为策略。这种灵活性使得游戏更加具有挑战性和趣味性。
5.3 图像处理中的滤镜选择
在图像处理软件中,滤镜是常用的功能之一。通过策略模式,可以将不同的滤镜算法封装成独立的策略类,并提供统一的接口供用户选择。这样,用户可以根据需要选择不同的滤镜来处理图像,例如模糊、锐化、颜色调整等。这种设计方式使得图像处理软件更加灵活和易于扩展,同时也提高了用户的操作体验和满意度。
综上所述,策略模式是一种强大的设计模式,它允许在运行时根据不同的策略选择不同的算法或行为。虽然它也有一些缺点,但在适当的场景下使用策略模式可以带来显著的优点和好处。
6、策略模式与其他设计模式的比较
6.1 与状态模式的对比
结构差异:
策略模式在结构上相对简单,通常包含一个环境类(Context),它持有一个策略接口(Strategy)的引用,以及多个实现了该接口的具体策略类(ConcreteStrategy)。
状态模式则更为复杂,它包含了一系列的状态对象(State),这些状态对象可以持有自己的数据,并定义了在不同状态下对象应该采取的行为。状态模式中的环境类(Context)通常持有一个当前状态对象的引用,并委托给该状态对象处理请求。
行为变化:
策略模式关注的是算法或行为的变化,这些算法或行为是独立且可替换的。客户端可以在运行时选择不同的策略对象,以实现不同的行为。
状态模式则关注的是对象在不同状态下的行为变化,以及状态之间的切换。它允许对象在内部状态改变时自动改变其行为。
使用场景:
策略模式适用于系统中存在多种算法或行为,且这些算法或行为可以独立变化的情况。
状态模式适用于对象的行为随其内部状态改变而改变,且这些状态之间的切换逻辑较为复杂的情况。
6.2 与模板方法模式的对比
结构差异:
策略模式包含环境类、策略接口和具体策略实现类。
模板方法模式则包含一个抽象类(AbstractClass),该类中定义了一个算法的骨架,并包含了一些抽象方法或钩子方法(Hook),这些方法的具体实现由子类提供。
关注点:
策略模式关注的是算法或行为的替换和选择,它允许客户端在运行时动态地选择不同的策略对象。
模板方法模式关注的是算法的骨架和具体步骤的延迟实现。它提供了一个算法的总体结构,但允许子类根据需要重写或扩展某些步骤。
使用场景:
策略模式适用于需要动态选择不同算法或行为的情况。
模板方法模式适用于算法或行为的基本结构固定,但具体实现因子类而异的情况。
6.3 与装饰者模式的对比
结构差异:
策略模式和装饰者模式在结构上有所不同。策略模式主要包含环境类、策略接口和具体策略实现类。
装饰者模式则包含一个基本的组件类(Component)和多个装饰者类(Decorator),每个装饰者类都持有一个组件的引用,并可以在该组件的基础上添加额外的行为或功能。
关注点:
策略模式关注的是算法或行为的替换和选择。
装饰者模式关注的是在不改变类结构的情况下,动态地为对象添加额外的功能或行为。
使用场景:
策略模式适用于需要动态选择不同算法或行为的情况。
装饰者模式适用于需要在不修改原有类代码的情况下,为对象添加新的功能或行为的情况。
7、高级话题与最佳实践
7.1 使用智能指针管理策略对象
在C++等语言中,使用智能指针(如std::shared_ptr或std::unique_ptr)来管理策略对象可以自动处理内存分配和释放,避免内存泄漏和悬挂指针等问题。智能指针通过引用计数或其他机制来确保对象在不再被需要时自动销毁。
使用智能指针管理策略对象时,需要注意以下几点:
确保策略对象被正确地创建和初始化。
避免在多个线程之间共享同一个智能指针,除非该智能指针是线程安全的。
在不再需要策略对象时,确保它能够被正确地销毁和释放。
7.2 策略工厂模式简化策略创建
为了简化策略对象的创建过程,可以使用工厂模式(如简单工厂、工厂方法或抽象工厂)来封装策略对象的创建逻辑。这样,客户端只需要与工厂接口交互,而无需了解具体策略类的实现细节。
使用策略工厂模式时,需要注意以下几点:
工厂类应该提供一个统一的接口来创建不同类型的策略对象。
工厂类应该能够处理策略对象的创建和初始化过程中的任何异常或错误。
客户端应该通过工厂接口来获取策略对象,而不是直接实例化具体策略类。
7.3 线程安全考虑
在多线程环境中使用策略模式时,需要考虑线程安全问题。如果策略对象的状态在多个线程之间共享,那么需要采取适当的同步机制来确保线程安全。
以下是一些常见的线程安全考虑:
使用线程安全的智能指针来管理策略对象。
在策略对象的方法中添加适当的同步机制(如互斥锁或读写锁)。
避免在多个线程之间共享可变的状态信息,除非使用了适当的同步机制。
在设计策略模式时,尽量将状态信息封装在策略对象内部,并通过不可变对象或线程安全的集合来传递状态信息。
总之,在使用策略模式时,需要根据具体的应用场景和需求来选择合适的设计和实现方式,并关注线程安全、内存管理等高级话题和最佳实践。
8、总结
8.1 策略模式的核心价值
策略模式的核心价值在于提供了一种灵活且可扩展的方式来处理算法或行为的变化。它将算法或行为封装成独立的策略类,使得这些策略可以互换,而客户端代码则可以根据需要动态地选择不同的策略。这种设计使得系统更加灵活,易于维护和扩展。策略模式的核心价值主要体现在以下几个方面:
提高了系统的灵活性和可扩展性:通过封装不同的算法或行为,策略模式使得系统可以轻松地添加新的策略,而无需修改现有的客户端代码。
简化了客户端代码:客户端代码只需要与抽象策略类进行交互,而无需关心具体的策略实现,从而简化了客户端代码。
实现了算法或行为的可重用性:不同的策略类可以共享相同的接口或抽象类,这使得算法或行为可以在不同的上下文中重用。
增强了系统的可维护性:由于策略模式将算法或行为封装在独立的类中,因此当某个算法或行为需要修改时,只需要修改相应的策略类即可,而不会影响到其他部分的代码。
8.2 何时使用策略模式
策略模式适用于以下场景:
算法或行为有多种变体:当系统需要实现多种算法或行为,并且这些算法或行为之间可以互换时,可以使用策略模式。
避免使用多重条件语句:如果系统中的算法或行为选择依赖于多个条件语句,这会导致代码难以理解和维护。此时,可以使用策略模式将不同的算法或行为封装成独立的类,从而消除多重条件语句。
需要动态选择算法或行为:当系统中的算法或行为需要在运行时动态选择时,可以使用策略模式。客户端代码可以根据需要选择不同的策略类,从而实现动态的行为选择。
需要封装复杂的算法或行为:如果系统中的某个算法或行为非常复杂,需要将其封装起来以便更好地理解和维护,那么可以使用策略模式。
8.3 后续学习资源推荐
为了深入学习策略模式及其在实际项目中的应用,以下是一些推荐的学习资源:
《设计模式:可复用面向对象软件的基础》(Erich Gamma等著):这本书是设计模式领域的经典之作,详细介绍了包括策略模式在内的多种设计模式。
《重构:改善既有代码的设计》(Martin Fowler著):这本书提供了许多实用的重构技巧,其中也包括对策略模式的讨论和应用。
9、参考文献与进一步阅读
9.1 相关书籍推荐
《设计模式:可复用面向对象软件的基础》:这本书是设计模式领域的权威之作,详细阐述了各种设计模式的概念、原理和应用场景。对于想要深入理解策略模式及其在其他设计模式中的关系的读者来说,这本书是不可或缺的。
《重构:改善既有代码的设计》:这本书提供了许多实用的重构技巧和方法,其中也包括对策略模式的讨论和应用。通过这本书,你可以学习如何在现有代码中应用策略模式来改善代码的可读性和可维护性。
相关文章:
《C++设计模式》策略模式
文章目录 1、引言1.1 什么是策略模式1.2 策略模式的应用场景1.3 本文结构概览 2、策略模式的基本概念2.1 定义与结构2.2 核心角色解析2.2.1 策略接口(Strategy)2.2.2 具体策略实现(ConcreteStrategy)2.2.3 上下文(Cont…...
细说STM32F407单片机轮询方式CAN通信
目录 一、项目介绍 二、项目配置 1、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator 2、CAN1 (1)Bit Timings Parameters组,位时序参数 (2)Basic Parameters组,基本参数 (3)…...
perf:对hutool的BeanUtil工具类做补充
分享一个自定义的BeanUtil,继承的是hutool的工具类,然后自己扩充了几个方法; 1、实现了两个对象覆盖非空属性的功能(经常使用),不需要设置CopyOptions; 2、两个对象,对指定前缀的属…...
【数据结构】栈与队列(FIFO)
在阅读该篇文章之前,可以先了解一下堆栈寄存器和栈帧的运作原理:<【操作系统】堆栈寄存器sp详解以及栈帧>。 栈(FILO) 特性: 栈区的存储遵循着先进后出的原则。 例子: 枪的弹夹,最先装进去的子弹最后射出来,最后装入的子弹…...
02.01、移除重复节点
02.01、[简单] 移除重复节点 1、题目描述 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 2、解题思路 为了实现这一目标,我们可以使用一个哈希表(或集合)来记录已经遇到的节点值,逐步遍历链表并删…...
Spring thymeleaf 的快速默认搭建使用
Spring thymeleaf 的快速默认搭建使用 thymeleaf 的搭建Pom 文件 thymeleaf 的使用Controller返回参数String资源文件路径访问端点显示HTML页面 thymeleaf 的搭建 Pom 文件 Pom 文件引入 spring-boot-starter-thymeleaf 依赖 <dependency><groupId>org.springfra…...
unity学习3:如何从github下载开源的unity项目
目录 1 网上别人提供的一些github的unity项目 2 如何下载github上的开源项目呢? 2.1.0 下载工具 2.1.1 下载方法1 2.1.2 下载方法2(适合内部项目) 2.1.3 第1个项目 和第4项目 的比较 第1个项目 第2个项目 第3个项目 2.1.4 下载方法…...
印象笔记07——试一试PDF标注
印象笔记07——试一试PDF标注 [!CAUTION] 根据第六期,我再次查询了资料,印象笔记还是有一些可圈可点的功能的(当然部分有平替),针对会员作用,开发使用场景虽然是逆向的,但我坚信这是一部分人的现…...
Logback的使用
1、基本认识 logback官方文档:http://logback.qos.ch 具体样例:https://www.baeldung.com/logback 从下面依赖关系图可以看见,Springboot的核心启动器spring-boot-stater依赖了spring-boot-starter-looging,而这个就是日志的启动器…...
沙箱模拟支付宝支付3--支付的实现
1 支付流程实现 演示案例 主要参考程序员青戈的视频【支付宝沙箱支付快速集成版】支付宝沙箱支付快速集成版_哔哩哔哩_bilibili 对应的源码在 alipay-demo: 使用支付宝沙箱实现支付功能 - Gitee.com 以下是完整的实现步骤 1.首先导入相关的依赖 <?xml version"1…...
微信小程序滑动解锁、滑动验证
微信小程序简单滑动解锁 效果 通过 movable-view (可移动的视图容器,在页面中可以拖拽滑动)实现的简单微信小程序滑动验证 movable-view 官方说明:https://developers.weixin.qq.com/miniprogram/dev/component/movable-view.ht…...
Redis的常用命令
Redis中文字典网站 redis 命令手册https://redis.com.cn/commands.html Keys * 查看当前库所有的key exists ke 判断某个key是否存在 type key查看你的key是什么类型 Del key删除执行的key数据 unlink key非阻塞删除,仅仅将keys从keyspace元数据中删除…...
国内Ubuntu环境Docker部署 ComfyUI
国内Ubuntu环境Docker部署 ComfyUI 趁着这两天用docker部署了 Stable Diffusion,顺手也安排上 ComfyUI。 ComfyUI相比 Stable Diffusion 原生的 WEB UI,更容易让人了解其出图的过程,极其适合学习与研究。拼接其强大的插件节点、不仅能够实现文…...
Meta 的新策略,将 AI 生成的角色整合到其社交媒体平台
一、Meta新年规划及引人注目的举措 多元规划背景:在新的一年,Meta制定了多维度的战略规划,旨在巩固并拓展其在科技领域的影响力。增强现实与元宇宙是其长期布局的重点方向,期望借此塑造未来互联网的交互形态;面对TikTo…...
玩转OCR | 腾讯云智能结构化OCR初次体验
目录 一、什么是OCR(需要了解) 二、产品概述与核心优势 产品概述 智能结构化能做什么 举例说明(选看) 1、物流单据识别 2、常见证件识别 3、票据单据识别 4、行业材料识别 三、产品特性 高精度 泛化性 易用性 四、…...
蓝桥杯JAVA--003
需求 2.代码 public class RegularExpressionMatching {public boolean isMatch(String s, String p) {if (p.isEmpty()) {return s.isEmpty();}boolean firstMatch !s.isEmpty() && (s.charAt(0) p.charAt(0) || p.charAt(0) .);if (p.length() > 2 && p…...
STC51和STM32单片机烧录引脚的完整名称
STC51 和 STM32 单片机烧录引脚的完整名称 1. STC51 单片机的烧录引脚 STC51 单片机通过 串口(UART) 进行程序下载,主要引脚如下: 引脚名称完整英文名称说明TXDTransmit Data串口发送引脚,用于发送数据。RXDReceive…...
阿里云大模型ACP高级工程师认证模拟试题
阿里云大模型ACP高级工程师认证模拟试题 0. 引言1. 模拟试题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题单选题单选题多选题多选题单选题多选题单…...
深入理解计算机中的补码、反码、原码
问题: 我们每天用的钟表,其实只有1~12这12个数字,但我们日常会说13点、17点之类的。 问:13点在钟表上哪个位置? 答:很简单嘛,1点的位置。 你不觉得奇怪吗,为啥13点会和1点在同一个位…...
调试:用电脑开发移动端网页,然后用手机真机调试
一、背景 电脑开发移动端,然后想真机调试... 二、实现 2.1、电脑和手机链接相同局域网 2.2、pnpm run dev 启动项目 2.3、浏览器访问 localhost:3001/login 2.4、Windowsr 输入cmd,在cmd输入 ipconfig 2.5、浏览器访问 ip地址加/login 2.6、手机端…...
深入浅出:Spring Boot 自定义消息转换器的实现与应用
Spring Boot 作为当前最流行的 Java Web 开发框架之一,广泛应用于微服务架构、企业级应用等多个场景。Spring Boot 提供了灵活且易于扩展的架构,其中消息转换器(Message Converter)是其重要组成部分。消息转换器在 Spring Boot 中…...
基于AI大模型的医院SOP优化:架构、实践与展望
一、引言 1.1 研究背景与意义 近年来,人工智能(AI)技术取得了迅猛发展,尤其是大模型的出现,为各个领域带来了革命性的变化。在医疗领域,AI 医疗大模型正逐渐崭露头角,展现出巨大的应用潜力。随着医疗数据的海量积累以及计算能力的大幅提升,AI 医疗大模型能够对复杂的…...
Maven项目集成SQL Server的完整教程:从驱动配置到封装优化
前言 在最近的系统对接过程中,由于对方团队不熟悉技术,最终选择直接提供 SQL Server 视图。本文详细记录了使用 Maven 集成 SQL Server 驱动的过程,以及从配置到查询的各个关键步骤,还包括注意事项与常见问题,希望对需…...
Java 21 优雅和安全地处理 null
在 Java 21 中,判断 null 依然是开发中常见的需求。通过使用现代 Java 提供的工具和特性,可以更加优雅和安全地处理 null。 1. 使用 Objects.requireNonNull Objects.requireNonNull 是标准的工具方法,用于快速判断并抛出异常。 示例 import java.util.Objects;public c…...
Java(四十四)file
Java中的file类:代表文件或者文件夹(目录)类,也就是说将文件或者文件夹通过File类来封装成对象。 一:常用的构造方法: 使用file类,需要通过构造方法创建一个file对象。 1:public File(String pathname) public static void main(String[] args) {File fl = new File(&…...
【51项目】51单片机自制小霸王游戏机
视频演示效果: 纳新作品——小霸王游戏机 目录: 目录 视频演示效果: 目录: 前言:...
【ArcGISPro/GeoScenePro】检查多光谱影像的属性并优化其外观
数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 操作 其他数据 检查影像的属性 熟悉检查您正在使用的栅格属性非常重要。...
《新概念模拟电路》-三极管
三极管 本系列文章主要学习《新概念模拟电路》中的知识点。在工作过程中,碰到一些问题,于是又翻阅了模电这本书。我翻阅的是ADI出版的,西安交通大学电工中心杨建国老师编写的模电书。 <模电>和《数电》这两本书是电子学的专业基础课&…...
K 近邻算法入门指南:明氏距离与皮尔森距离的基础讲解
1、K近邻算法介绍 K近邻(k-Nearest Neighbor,KNN)分类算法的思路是:在特征空间中,如果一个样本附近的k个最近样本的大多数属于某一个类别,则该样本也属于这个类别。K近邻算法中,所选择的邻居都是已经正确分类的对象。…...
如何验证imap是否生效
要验证您的 Outlook 邮箱是否启用了 IMAP 并且正常工作,可以按照以下步骤进行操作: 1. 确认 Outlook 邮箱是否启用 IMAP 步骤: 登录到您的 Outlook Web 账户: 打开浏览器,访问 Outlook.com 或 Microsoft 365 Outlook…...
MySQL 06 章——多表查询
多表查询,也称为关联查询,是指两个表或多个表一起完成查询操作 前提条件,这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段的。这个关联字段可能建立了外键,也可能没…...
转换VMware Esxi 虚拟机到 Windows2019 Hyper-V Server
Hyper-v专用P2V工具disk2vhd实际应用 工具介绍 disk2vhd是一个非常小的P2V转换工具,可以将你的物理服务器或Esxi vm 转换成为VHD或者vhdx格式的虚拟硬盘文件,然后在虚拟平台上作为一台虚拟机来使用。目前disk2vhd的最新版本是2.0.1,已经可以…...
头歌实训2-1:面向对象程序设计-基础部分
第1关:定义银行员工类BankEmployee 本关任务:编写银行员工类BankEmployee,要求: 1.银行员工类的属性包括姓名name,工号num,工资salary 2.姓名name和工号num设置为私有属性,并将salay设置为默认参数3000 平…...
超高分辨率 图像 分割处理
文章大纲 制造业半导体领域高分辨率图像半导体数据集开源的高分辨率晶圆图像数据集1. WM-811K数据集2. Kaggle上的WM-811K Clean Subset数据集医疗 病理领域高分辨率图像1. Camelyon+2. CAMELYON173. CPIA Dataset4. UCF-WSI-Dataset航拍 遥感中的高分辨率 图像航拍遥感领域高分…...
使用 apply 方法将其他列的值传入 DataFrame 或 Series 的函数,来进行更灵活的计算或操作
可以使用 apply 方法将其他列的值传入 DataFrame 或 Series 的函数,来进行更灵活的计算或操作。apply 方法允许你逐行或逐列地对 DataFrame 或 Series 的元素进行操作,而且你可以将其他列的值作为参数传递给函数。 示例:使用 apply 结合其他…...
[CTF/网络安全] 攻防世界 warmup 解题详析
查看页面源代码,发现source.php 得到一串代码,进行代码审计: <?phpclass emmm{public static function checkFile(&$page){$whitelist ["source">"source.php","hint">"hint.php"];…...
力扣第389题—找不同
class Solution:def findTheDifference(self, s: str, t: str) -> str:# 对字符串 s 和 t 进行排序a sorted(s)b sorted(t)# 比较排序后的两个列表for i in range(len(a)):if a[i] ! b[i]:return b[i]# 如果前面的比较没有找到差异,那么差异字符在 t 的最后一个…...
vite6+vue3+ts+prettier+eslint9配置前端项目(后台管理系统、移动端H5项目通用配置)
很多小伙伴苦于无法搭建一个规范的前端项目,导致后续开发不规范,今天给大家带来一个基于Vite6TypeScriptVue3ESlint9Prettier的搭建教程。 目录 一、基础配置1、初始化项目2、代码质量风格的统一2.1、配置prettier2.2、配置eslint2.3、配置typescript 3、…...
滴滴数据分析80道面试题及参考答案
如何衡量分类好坏? 衡量分类好坏有多种方法,常用的有准确率、精确率、召回率、F1 值、ROC 曲线与 AUC 值等。 准确率:是指分类正确的样本数占总样本数的比例,计算公式为:准确率 = (分类正确的样本数)/(总样本数)。准确率越高,说明分类器整体的分类效果越好,但在正负…...
嵌入式应用软件开发中C语言方向面试题
嵌入式应用软件开发中C语言方向面试题随笔 前言一、C语言基础二、嵌入式开发相关三、硬件相关知识五、实际编程问题前言 做嵌入式开发这么多年了,简单记录下C语言方向常见面试题,这里是应用软件方向的。 一、C语言基础 C语言的指针与数组的区别是什么?指针:指针是一个变量…...
vue3中mixins替代方案
使用自定义 Hooks(Composables) 自定义 Hooks 是一种基于函数的代码复用方式,可以在 setup 函数中使用。它允许将组件的逻辑分割成更小的、可复用的部分。 useCounter.js //useCounter.js import { ref, onMounted } from vue;export func…...
线性代数自学资源推荐我的个人学习心得
1.前言 自己这个学期的课程基本上就结束了,因此我自己就开始学习下个学期的课程--线性代数,也是我们在大学里面的最后一门数学课程了; 之前有过一些这个线性代数的基础,当时主要是参加这个数学建模比赛去学习这个matlab吗&#…...
WordPress Crypto 插件 身份认证绕过漏洞复现(CVE-2024-9989)
0x01 产品简介 WordPress Crypto插件是指那些能够为WordPress网站提供加密货币支付、信息显示或交易功能的插件。这些插件通常与WordPress电子商务插件(如WooCommerce)集成,使网站能够接受多种加密货币支付,或展示加密货币实时信息。支持多种加密货币支付,付款直接进入钱…...
软件逆向之OD基础
OD程序目录 plugin:存放OD所有插件 UDD:存放程序临时的数据,比如:程序注释、断点等 ollydbg.ini:存放OD自身配置的属性表 OLLYDBG.HLP:OD的帮助手册 OD断点 1.软件断点: 介绍:…...
C++并发编程之内存顺序一致性
std::memory_order_seq_cst 是 C11 引入的内存模型中的一种内存顺序(memory order),全称为 Sequential Consistency(顺序一致性)。它是 C 中最严格的内存顺序,提供了最强的同步保证。下面详细解释其含义、意…...
软件测试面试题整理
一、人格相关问题 1、自我介绍结构 姓名工作年限简单介绍上家公司的行业主要负责内容个人优势短期内的职业规划应聘该岗位的原因 2、对未来的发展方向怎么看 3、你对测试最大的兴趣在哪里?为什么? 二、技术相关问题 1、测试理论以及应用 1、给你一个…...
Java中如何实现线程安全的单例模式?
目录 1、懒汉式(线程安全) 2、饿汉式(线程安全) 3、双重校验锁(线程安全) 4、静态内部类(推荐) 5、枚举(最佳方法) 6、总结 在Java中,实现线…...
MYsql--------ubantu中安装mysql
在Ubuntu平台上下载、启动和关闭MySQL的方法如下: 下载安装MySQL 更新软件包列表:打开终端,输入以下命令,确保软件包列表是最新的。sudo apt update安装MySQL服务器:执行以下命令安装MySQL服务器。在安装过程中&…...
【Ubuntu】不能连上网络
1. ping路由器的IP地址 ping 192.168.1.1 如果ping不通的话,可能是网络故障导致的。需要重启配置ip地址。配置文件 sudo vi /etc/network/interface 2. ping 8.8.8.8 如果ping不通的话,可能是路由器不能链接往外网; 或者路由器显示了当…...
探索 AIGC 的基础知识:人工智能生成内容的全景视图
在数字化时代,人工智能生成内容(AIGC)正以前所未有的速度改变着我们的创作方式。本文将深入探讨 AIGC 的定义、构成要素、应用场景以及其带来的优势,帮助读者全面理解这一前沿技术。 1. AIGC 的定义与范围 人工智能生成内容&…...