当前位置: 首页 > article >正文

设计模式实践:模板方法、观察者与策略模式详解

目录

  • 1 模板方法
    • 1.1 模板方法基本概念
    • 1.2 实验
      • 1.2.1 未使用模板方法实现代码
      • 1.2.2 使用模板方法的代码
  • 2 观察者模式
    • 2.1 观察者模式基本概念
    • 2.2 实验
  • 3 策略模式
    • 3.1 策略模式基本概念
    • 3.2 实验

1 模板方法

1.1 模板方法基本概念

  • 定义:一个操作中的算法的骨架 ,而将一些步骤延迟到子类中。 Template Method使得子类可以不
    改变一个算法的结构即可重定义该算法的某些特定步骤。
  • 要点:
    • 最常用的设计模式,子类可以复写父类子流程,使父类的骨架流程丰富
    • 父类 protected 保护子类需要复写的子流程;这样子类的子流程只能父类来调用

1.2 实验

背景
某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代更新表演流程;

1.2.1 未使用模板方法实现代码

#include <iostream>
using namespace std;#if 0
class ZooShow {
public:void Show0() {cout << "show0" << endl;}void Show2() {cout << "show2" << endl;}
};class ZooShowEx {
public:void Show1() {cout << "show1" << endl;}void Show3() {cout << "show3" << endl;}
};// 不满足单一职责 , 开 扩展 修改闭原则
// 动物园固定流程,迭代创新
// 稳定和变化   一定的方向上变化
#else if 2
class ZooShow {
public:ZooShow(int type = 1) : _type(type) {}public:void Show() {if (Show0())PlayGame(); // 里氏替换Show1();Show2();Show3();}// 接口隔离 不要让用户去选择它们不需要的接口
private:void PlayGame() {cout << "after Show0, then play game" << endl;}private:bool Show0() {cout << _type << " show0" << endl;return true;}void Show1() {if (_type == 1) {cout << _type << " Show1" << endl;} else if (_type == 2) {cout << _type << " Show1" << endl;} else if (_type == 3) {}}void Show2() {if (_type == 20) {}cout << "base Show2" << endl;}void Show3() {if (_type == 1) {cout << _type << " Show1" << endl;} else if (_type == 2) {cout << _type << " Show1" << endl;}}
private:int _type;
};#endifint main () {
#if 0ZooShow *zs = new ZooShow;ZooShowEx *zs1 = new ZooShowEx;zs->Show0();zs1->Show1();zs->Show2();zs1->Show3();
#else if 2ZooShow *zs = new ZooShow(1);zs->Show();
#endifreturn 0;
}

分析:

  • 1.缺乏可扩展性
    在当前代码里,ZooShow 类的 Show 方法内包含了很多 if - else 条件判断,用来依据不同的 _type 值执行不同的逻辑。要是需要新增一种表演类型,就得修改 Show 方法,添加新的 if - else 分支。这违背了开闭原则(对扩展开放,对修改关闭),代码的可扩展性较差。例如,如果要增加 _type == 4 的表演流程,就得在各个方法里添加对应的判断逻辑。
  • 2.代码复用性低
    每个表演类型的逻辑都被硬编码在 ZooShow 类的各个方法中,不同表演类型之间的公共逻辑没有得到很好的复用。如果某些表演类型有相似的流程,当前代码无法有效复用这些公共部分,会造成代码冗余。
  • 3.违反单一职责原则
    ZooShow 类承担了过多的职责,它不仅定义了表演的流程,还包含了每种表演类型的具体逻辑**。当表演类型增多或者表演流程发生变化时,这个类会变得越来越复杂,难以维护**。
  • 4.可读性和可维护性差
    大量的 if - else 条件判断使得代码的逻辑变得复杂,降低了代码的可读性。而且,当需要修改或添加新的表演类型时,需要在多个方法中查找和修改相关逻辑,增加了维护的难度。

1.2.2 使用模板方法的代码

学习设计模式 我们可以通过这些 要点

  • 定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法。
  • 解决的问题
    确定点:算法骨架
    变化点:子流程需要变化
  • 代码结构
    基类中存骨架流程接口
    所有子流程对子类开放并且是虚函数
    多态使用方式
  • 符合哪些设计原则
    单一职责
    开闭
    依赖倒置:子类扩展时,需要依赖基类的虚函数实现;使用者只依赖接口
    封装变化点:protected
    接口隔离
    最小知道原则
  • 如何扩展
    实现子类继承基类,重写子流程
    通过多态调用方式使用
#include <iostream>
using namespace std;// 抽象基类,定义表演流程的模板
class ZooShowTemplate {
public:// 模板方法,定义表演的整体流程void Show() {if (Show0())PlayGame();Show1();Show2();Show3();}virtual ~ZooShowTemplate() {}protected:// 具体步骤的虚函数,可在子类中重写virtual bool Show0() {cout << "show0" << endl;return true;}virtual void PlayGame() {cout << "after Show0, then play game" << endl;}virtual void Show1() = 0;virtual void Show2() = 0;virtual void Show3() = 0;
};// 具体表演类型 1
class ZooShowType1 : public ZooShowTemplate {
protected:void Show1() override {cout << "1 Show1" << endl;}void Show2() override {cout << "base Show2" << endl;}void Show3() override {cout << "1 Show3" << endl;}
};// 具体表演类型 2
class ZooShowType2 : public ZooShowTemplate {
protected:void Show1() override {cout << "2 Show1" << endl;}void Show2() override {cout << "base Show2" << endl;}void Show3() override {cout << "2 Show3" << endl;}
};int main() {ZooShowTemplate* zs1 = new ZooShowType1();zs1->Show();ZooShowTemplate* zs2 = new ZooShowType2();zs2->Show();delete zs1;delete zs2;return 0;
}

解决的问题

  • 确定点(算法骨架):代码里 ZooShowTemplate 类的 Show 方法确定了表演流程这个算法骨架,固定了表演的整体执行顺序。
  • 变化点(子流程需要变化):不同类型的表演,如 ZooShowType1 和 ZooShowType2,它们的 Show1、Show2、Show3 具体实现是不同的,这就是子流程的变化点,通过继承基类并重写相应虚函数来实现不同的子流程

代码结构

  • 基类中存骨架流程接口:ZooShowTemplate 类中定义的 Show 方法就是骨架流程接口,它包含了整个表演流程的逻辑。
  • 所有子流程对子类开放并且是虚函数:Show0、PlayGame、Show1、Show2、Show3 这些子流程方法在 ZooShowTemplate 类中都被定义为虚函数,方便子类重写,实现不同的子流程逻辑。
  • 多态使用方式:在 main 函数中,通过基类指针 ZooShowTemplate* 分别指向 ZooShowType1 和 ZooShowType2 的对象,然后调用 Show 方法,运行时根据实际指向的子类对象调用相应子类重写的方法,体现了多态性。

符合的设计原则

  • 单一职责:ZooShowTemplate 类负责定义表演流程骨架,各个子类负责具体表演类型的子流程实现,职责划分清晰 ,每个类只专注于自己的职责。
  • 开闭:当需要新增一种表演类型时,如 ZooShowType3,只需创建一个新类继承 ZooShowTemplate 并重写相关虚函数,不需要修改 ZooShowTemplate 类的代码,对扩展开放,对修改关闭。
  • 依赖倒置:子类扩展时依赖基类的虚函数实现,比如 ZooShowType1 和 ZooShowType2 依赖 ZooShowTemplate 中定义的虚函数;使用者(main 函数)只依赖 ZooShowTemplate 这个抽象基类接口,而不是具体子类,降低了耦合度。
  • 封装变化点:在 ZooShowTemplate 类中,将一些可能变化的子流程方法(如 Show1、Show2 等)定义为虚函数,并且访问修饰符为 protected,对外部隐藏了具体实现细节,同时方便子类重写来实现变化。
  • 接口隔离:虽然代码中未明显体现接口隔离的典型场景,但从某种程度上,每个子类只实现自己需要的虚函数,没有被迫依赖不需要的接口方法。
  • 最小知道原则:子类只需要了解与自己相关的基类虚函数,不需要了解基类中其他不必要的实现细节,减少了类之间的信息交互。

如何扩展

  • 实现子类继承基类,重写子流程:如代码中 ZooShowType1 和 ZooShowType2 继承自 ZooShowTemplate,并重写了 Show1、Show2、Show3 等子流程方法,实现不同表演类型的定制。
  • 通过多态调用方式使用:在 main 函数中,通过基类指针调用 Show 方法,利用多态性根据实际子类对象调用相应的重写方法,实现不同表演类型的流程执行。

2 观察者模式

2.1 观察者模式基本概念

  • 定义:对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新
  • 特性
    • 松耦合:主题和观察者相互独立,主题无需知道观察者具体细节,只知其实现了观察者接口 。比如电商系统中商品信息(主题)变化,不同的展示模块(观察者)可独立更新,互不干扰。
    • 动态性:观察者可随时添加或移除,不影响系统其他部分 。例如新闻推送系统,新用户(观察者)可随时订阅(添加)或退订(移除)频道(主题)。

2.2 实验

背景:
气象站发布气象资料给数据中心,数据中心经过处理,将气象信息更新到两个不同的显示终端(A和B)
实现伪代码

#include <vector>//
class IDisplay {
public:virtual void Show(float temperature) = 0;virtual ~IDisplay() {}
};class DisplayA : public IDisplay {
public:virtual void Show(float temperature);
private:void jianyi();
};class DisplayB : public IDisplay{
public:virtual void Show(float temperature);
};class DisplayC : public IDisplay{
public:virtual void Show(float temperature);
};class WeatherData {
};class DataCenter {
public:void Attach(IDisplay * ob);void Detach(IDisplay * ob);void Notify() {float temper = CalcTemperature();for (auto iter = obs.begin(); iter != obs.end(); iter++) {(*iter)->Show(temper);}}// 接口隔离
private:virtual WeatherData * GetWeatherData();virtual float CalcTemperature() {WeatherData * data = GetWeatherData();// ...float temper/* = */;return temper;}std::vector<IDisplay*> obs;
};int main() {DataCenter *center = new DataCenter;IDisplay *da = new DisplayA();IDisplay *db = new DisplayB();IDisplay *dc = new DisplayC();center->Attach(da);center->Attach(db);center->Attach(dc);center->Notify();//-----center->Detach(db);center->Notify();return 0;
}

定义与解决的问题

  • 定义体现:观察者模式定义对象间一对多依赖关系,代码中 DataCenter 类相当于主题(被观察者),IDisplay 及其派生类**(DisplayA、DisplayB、DisplayC )相当于观察者** 。DataCenter 维护着多个 IDisplay 指针(观察者),当温度数据计算出来(主题状态变化)时,通知所有注册的观察者,符合一对多依赖关系的定义。
  • 稳定点与变化点
    • 稳定点:“一” 对应的是 DataCenter 类,它是主题,在系统中相对稳定,负责管理观察者和通知逻辑。
    • 变化点:“多” 对应的是 IDisplay 的不同派生类实例,如 DisplayA、DisplayB、DisplayC ,可以随时增加新的显示类(“多” 增加 ),或者移除已有的显示类(“多” 减少 ),比如在 main 函数中通过 Attach 和 Detach 方法进行添加和移除操作。

代码结构
-代码定义了主题类 DataCenter ,通过 std::vector<IDisplay*> 来存储观察者。观察者通过抽象接口 IDisplay 定义,具体观察者类 DisplayA、DisplayB、DisplayC 实现该接口。DataCenter 有 Attach、Detach 方法管理观察者,Notify 方法用于通知观察者。结构上满足观察者模式中主题与观察者的基本组织形式。
符合的设计原则

  • 面向接口编程:代码中定义了抽象接口 IDisplay ,DataCenter 类依赖 IDisplay 接口来管理观察者,而不是具体的观察者类(如 DisplayA、DisplayB 等 )。例如 DataCenter 的 Attach 方法接收 IDisplay * 类型参数,体现了面向接口编程,降低了耦合度。
  • 接口隔离:IDisplay 接口只定义了 Show 方法,每个具体的显示类只需要实现这个与自身显示功能相关的方法,没有被迫实现不必要的接口方法。并且 DataCenter 类内部也有一些方法(如 GetWeatherData 等 )相对隔离,符合接口隔离原则。
  • 封装变化点
    attach:在代码中对应 Attach 方法,用于将观察者(IDisplay 的派生类实例 )添加到 DataCenter 的观察者列表中,封装了增加观察者这个变化点。
    detach:对应 Detach 方法,用于从观察者列表中移除观察者,封装了减少观察者这个变化点。

如何扩展

若要扩展系统,比如增加新的显示方式(新的观察者 ),可以创建一个新的类继承自 IDisplay ,实现 Show 方法,然后在 main 函数中通过 DataCenter 的 Attach 方法将其添加到观察者列表中,就能参与到温度数据的显示通知流程中。

3 策略模式

3.1 策略模式基本概念

定义与核心思想

  • 定义一系列算法:把相关算法进行归纳整理,形成一个算法集合。比如电商系统中计算商品折扣,有固定折扣、满减折扣、会员专属折扣等不同算法 。
  • 封装每个算法:将每个算法独立封装在对应的策略类中。以支付场景为例,支付宝支付、微信支付、银行卡支付等,每种支付方式的实现细节都封装在各自的策略类里,外部无需了解具体支付流程(如网络请求、加密处理等 )。
  • 算法可相互替换:在运行时,可根据实际情况灵活切换不同策略,而不影响使用算法的客户端。例如地图导航,用户可在 “最短距离”“最快速度”“避开拥堵” 等不同路径规划策略间切换 。
    组成部分
  • 策略接口(抽象策略角色):定义算法的公共接口,规定算法应具备的方法签名。比如定义一个计算税费的策略接口,其中包含计算税费的抽象方法 calculateTax() 。
  • 具体策略类:实现策略接口,提供具体算法的实现。如上述计算税费的场景,有针对不同地区税率计算税费的具体策略类,像 “北京地区税费计算类”“上海地区税费计算类” 等,分别实现 calculateTax() 方法。
  • 上下文类:持有策略接口的引用,负责在合适时机调用策略对象的算法。例如电商系统中结算模块作为上下文类,它持有税费计算策略接口的引用,在结算时调用具体策略类(如根据收货地区选择对应地区的税费计算策略 )来计算税费。

3.2 实验

背景:某商场节假日有固定促销活动,为了加大促销力度,现提升国庆节促销活动规格
实现

class Context {};class ProStategy {
public:virtual double CalcPro(const Context &ctx) = 0;virtual ~ProStategy(); 
};
// cpp
class VAC_Spring : public ProStategy {
public:virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_QiXi : public ProStategy {
public:virtual double CalcPro(const Context &ctx){}
};
class VAC_QiXi1  : public VAC_QiXi {
public:virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_Wuyi : public ProStategy {
public:virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_GuoQing : public ProStategy {
public:virtual double CalcPro(const Context &ctx){}
};class VAC_Shengdan : public ProStategy {
public:virtual double CalcPro(const Context &ctx){}
};class Promotion {
public:Promotion(ProStategy *sss) : s(sss){}~Promotion(){}double CalcPromotion(const Context &ctx){return s->CalcPro(ctx);}
private:ProStategy *s;
};int main () {Context ctx;ProStategy *s = new VAC_QiXi1();Promotion *p = new Promotion(s);p->CalcPromotion(ctx);return 0;
}

解决的问题

  • 稳定点:在该商场促销场景中,“客户端与算法的调用关系” 是稳定点。从代码看,Promotion 类(客户端)通过构造函数接收 ProStategy 指针(算法相关),并在 CalcPromotion 方法中固定地调用 s->CalcPro(ctx) 来执行促销算法,这种调用关系相对稳定。
  • 变化点
    • 新加算法:当商场要增加新的促销活动时,比如后续可能新增某个节日的促销策略,就需要添加新的具体策略类。像代码中如果要新增 “元旦促销策略”,可以创建新类继承自 ProStategy 并实现 CalcPro 方法。
    • 算法内容改变:已有的促销策略(如 VAC_QiXi 等类 ),其内部的促销计算逻辑(CalcPro 方法的实现 )可能会根据商场需求进行调整和改变。
      代码结构
      定义了抽象策略类 ProStategy ,其中声明了纯虚函数 CalcPro ,用于定义促销算法的接口。一系列具体策略类(VAC_Spring、VAC_QiXi 等 )继承自 ProStategy ,并实现 CalcPro 方法,各自代表不同节日的促销算法。Context 类目前为空,但在策略模式中通常用于存储上下文相关信息,供策略类使用。
      Promotion 类作为上下文类,持有 ProStategy 指针,通过构造函数进行依赖注入(接收具体的策略对象 ),并在 CalcPromotion 方法中调用策略对象的 CalcPro 方法来执行促销计算。

设计原则

  • 接口隔离
    • 依赖注入:Promotion 类通过构造函数 Promotion(ProStategy *sss) 将具体的促销策略对象注入进来,实现了类与具体策略的解耦。比如在 main 函数中可以灵活地将不同的 ProStategy 子类对象(VAC_QiXi1 等 )注入到 Promotion 中。
    • 解决通过一个接口解决两个类的依赖:ProStategy 接口将 Promotion 类和具体的促销策略类(如 VAC_QiXi 等 )解耦,使得 Promotion 类只依赖于抽象接口,而不依赖具体策略类的实现细节,解决了它们之间的依赖问题。
  • 面向接口编程:整个代码围绕 ProStategy 接口展开,Promotion 类依赖 ProStategy 接口,而不是具体的策略类。在 main 函数中也是通过 ProStategy 指针来操作具体的策略对象,体现了面向接口编程,降低了代码间的耦合度。
  • 开闭原则:当需要新增促销策略(如新增节日促销 )时,只需创建新的类继承 ProStategy 并实现 CalcPro 方法,无需修改现有的 Promotion 类以及其他已有的策略类代码,对扩展开放,对修改关闭。
    其实还有一个组合优于继承的原则

如何扩展代码
若要扩展代码,比如增加新的促销策略,只需创建一个新的类继承自 ProStategy ,并实现 CalcPro 方法。然后在 main 函数中,创建该新策略类的对象,并将其注入到 Promotion 类中,即可使用新的促销策略。例如新增 “中秋促销策略”,可以编写一个新类继承 ProStategy ,实现 CalcPro 方法来定义中秋促销的计算逻辑,然后在 main 函数中按现有方式使用这个新策略。
怎么调用

 ProStategy *s = new VAC_QiXi1();Promotion *p = new Promotion(s);p->CalcPromotion(ctx);

多态调用

相关文章:

设计模式实践:模板方法、观察者与策略模式详解

目录 1 模板方法1.1 模板方法基本概念1.2 实验1.2.1 未使用模板方法实现代码1.2.2 使用模板方法的代码 2 观察者模式2.1 观察者模式基本概念2.2 实验 3 策略模式3.1 策略模式基本概念3.2 实验 1 模板方法 1.1 模板方法基本概念 定义&#xff1a;一个操作中的算法的骨架 &…...

Rockchip 显示架构

对于 Rockchip 平台,主要有以下几种显示架构可供选择: Qt + WaylandQt + EGLFSEGL program + X11WaylandNone多窗口的功能需求,选择: X11Wayland桌面的功能需求,选择: X114K 视频播放 + 全屏:Qt + WaylandQt + EGLFSX11Wayland4K 视频播放 + 多窗口: X11Qt + WaylandWa…...

Edge 浏览器推出 Copilot Vision:免费实时解析屏幕内容;Aqua Voice:极速 AI 语音输入工具丨日报

开发者朋友们大家好 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看…...

async-profiler火焰图找出耗CPU方法

事情起于开发应用对依赖的三方包&#xff08;apache等等&#xff09;进行了升级后&#xff08;主要是升级spring&#xff09;&#xff0c;CPU的使用率较原来大幅提升&#xff0c;几个应用提升50%-100%。 查找半天&#xff0c;对比每次版本的cpu火焰图&#xff0c;看不出有什么…...

@Autowird 注解与存在多个相同类型对象的解方案

现有一个 Student 类&#xff0c;里面有两个属性&#xff0c;分别为 name 和 id&#xff1b;有一个 StuService 类&#xff0c;里面有两个方法&#xff0c;返回值均为类型为 Student 的对象&#xff1b;还有一个 StuController 类&#xff0c;里面有一个 Student 类型的属性&am…...

WordPiece 详解与示例

WordPiece详解 1. 定义与背景 WordPiece 是一种子词分词算法,由谷歌于2012年提出,最初用于语音搜索系统,后广泛应用于机器翻译和BERT等预训练模型。其核心思想是将单词拆分为更小的子词单元(如词根、前缀/后缀),从而解决传统分词方法面临的词汇表过大和未知词(OOV)处…...

PVE+CEPH+HA部署搭建测试

一、基本概念介绍 Proxmox VE ‌Proxmox Virtual Environment (Proxmox VE)‌ 是一款开源的虚拟化管理平台&#xff0c;基于 Debian Linux 开发&#xff0c;支持虚拟机和容器的混合部署。它提供基于 Web 的集中管理界面&#xff0c;简化了计算、存储和网络资源的配置与监控。P…...

【Leetcode 每日一题 - 补卡】1534. 统计好三元组

问题背景 给你一个整数数组 a r r arr arr&#xff0c;以及 a 、 b 、 c a、b 、c a、b、c 三个整数。请你统计其中好三元组的数量。 如果三元组 ( a r r [ i ] , a r r [ j ] , a r r [ k ] ) (arr[i], arr[j], arr[k]) (arr[i],arr[j],arr[k]) 满足下列全部条件&#xff…...

ROS ROS2 机器人深度相机激光雷达多传感器标定工具箱

系列文章目录 目录 系列文章目录 前言 三、标定目标 3.1 使用自定义标定目标 四、数据处理 4.1 相机数据中的标定目标检测 4.2 激光雷达数据中的标定目标检测 输入过滤器&#xff1a; 正常估算&#xff1a; 区域增长&#xff1a; 尺寸过滤器&#xff1a; RANSAC&a…...

android rtsp 拉流h264 h265,解码nv12转码nv21耗时卡顿问题及ffmpeg优化

一、 背景介绍及问题概述 项目需求需要在rk3568开发板上面&#xff0c;通过rtsp协议拉流的形式获取摄像头预览&#xff0c;然后进行人脸识别 姿态识别等后续其它操作。由于rtsp协议一般使用h.264 h265视频编码格式&#xff08;也叫 AVC 和 HEVC&#xff09;是不能直接用于后续处…...

熊海cms代码审计

目录 sql注入 1. admin/files/login.php 2. admin/files/columnlist.php 3. admin/files/editcolumn.php 4. admin/files/editlink.php 5. admin/files/editsoft.php 6. admin/files/editwz.php 7. admin/files/linklist.php 8. files/software.php 9. files…...

滑动窗口209. 长度最小的子数组

1.题目 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; 输入&…...

SQL(8):INSERT INTO SELECT与SELECT INTO,选数据出来,放到另一个表中

INSERT INTO SELECT 语句从一个表复制数据&#xff0c;然后把数据插入到一个已存在的表中&#xff1b; SELECT INTO 语句从一个表复制数据&#xff0c;然后把数据插入到另一个新表中 想象一下你有两个本子&#xff08;数据库里的表&#xff09;&#xff1a; 本子A (源头)&…...

DeepSeek 与开源:肥沃土壤孕育 AI 硕果

当 DeepSeek 以低成本推理、多模态能力惊艳全球时&#xff0c;人们惊叹于国产AI技术的「爆发力」&#xff0c;却鲜少有人追问&#xff1a;这份爆发力的根基何在&#xff1f; 答案&#xff0c;藏在中国开源生态二十余年的积淀中。 从倪光南院士呼吁「以开源打破垄断」&#xf…...

2025高频面试算法总结篇【动态规划】

文章目录 直接刷题链接直达编辑距离最长回文子串完全平方数最长递增子序列正则表达式匹配零钱兑换鸡蛋掉落单词拆分 直接刷题链接直达 动态规划&#xff08;Dynamic Programming, DP&#xff09;是一种通过拆解子问题并利用子问题的最优解来构建整体问题的最优解的方法&#x…...

Maven中clean、compil等操作介绍和Pom.xml中各个标签介绍

文章目录 前言Maven常用命令1.clean2.vaildate3.compile4.test5.package6.verify7.install8.site9.deploy pom.xml标签详解格式<?xml version"1.0" encoding"UTF-8"?>(xml版本和编码)modelVersion&#xff08;xml版本&#xff09;groupId&#xff…...

力扣刷题-热题100题-第35题(c++、python)

146. LRU 缓存 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/lru-cache/?envTypestudy-plan-v2&envIdtop-100-liked 双向链表哈希表 内置函数 对于c有list可以充当双向链表&#xff0c;unordered_map充当哈希表&#xff1b;python有OrderedDic…...

Nautilus 正式发布:为 Sui 带来可验证的链下隐私计算

作为 Sui 安全工具包中的强大新成员&#xff0c;Nautilus 现已上线 Sui 测试网。它专为 Web3 开发者打造&#xff0c;支持保密且可验证的链下计算。Nautilus 应用运行于开发者自主管理的可信执行环境&#xff08;Trusted Execution Environment&#xff0c;TEE&#xff09;中&a…...

云服务器CVM标准型S5实例性能测评——2025腾讯云

腾讯云服务器CVM标准型S5实例具有稳定的计算性能&#xff0c;CPU采用采用 Intel Xeon Cascade Lake 或者 Intel Xeon Cooper Lake 处理器&#xff0c;主频2.5GHz&#xff0c;睿频3.1GHz&#xff0c;CPU内存配置2核2G、2核4G、4核8G、8核16G等配置&#xff0c;公网带宽可选1M、3…...

优化方法介绍(二)——BFGS 方法介绍

优化方法介绍(二) 本博客是一个系列博客,主要是介绍各种优化方法,使用 matlab 实现,包括方法介绍,公式推导和优化过程可视化 1 BFGS 方法介绍 BFGS 的其实就是一种改良后的牛顿法,因为计算二阶导数 Hessian 矩阵所需的计算资源是比较大的,复杂度为 O ( 2 ⋅ n 2 ) …...

leetcode面试经典算法题——2

链接&#xff1a;https://leetcode.cn/studyplan/top-interview-150/ 20. 有效的括号 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#x…...

Ubuntu20.04安装企业微信

建议先去企业微信官网看一下有没有linux版本&#xff0c;没有的话在按如下方式安装&#xff0c;不过现在是没有的。 方案 1、使用docker容器 2、使用deepin-wine 3、使用星火应用商店 4. 使用星火包deepin-wine 5、使用ukylin-wine 本人对docker不太熟悉&#xff0c;现…...

在Ubuntu服务器上部署xinference

一、拉取镜像 docker pull xprobe/xinference:latest二、启动容器&#xff08;GPU&#xff09; docker run -d --name xinference -e XINFERENCE_MODEL_SRCmodelscope -p 9997:9997 --gpus all xprobe/xinference:latest xinference-local -H 0.0.0.0 # 启动一个新的Docker容…...

异步编程——微信小程序

1. 前言 引用来自&#xff1a;微信小程序开发中的多线程处理与异步编程_微信小程序 多线程-CSDN博客 微信小程序是基于JavaScript开发的&#xff0c;与浏览器JavaScript不同&#xff0c;小程序运行在WebView内部&#xff0c;没有多线程的概念。小程序的 JavaScript 是单线程的…...

Hive null safe的用法

总结: null safe 是用<> 代表比较&#xff0c;而不是用 。null <> null 返回 true&#xff0c; 而 null null 代表 false。 NULL 和任意字符比较都返回 NULL&#xff0c;而不是 true 或者 false。如 SELECT 1 1, NULL NULL, 1 NULL;输出 true NULL NULL如果我…...

STM32 四足机器人常见问题汇总

文章不介绍具体参数&#xff0c;有需求可去网上搜索。 特别声明&#xff1a;不论年龄&#xff0c;不看学历。既然你对这个领域的东西感兴趣&#xff0c;就应该不断培养自己提出问题、思考问题、探索答案的能力。 提出问题&#xff1a;提出问题时&#xff0c;应说明是哪款产品&a…...

鸿蒙NEXT开发文件预览工具类(ArkTs)

import { uniformTypeDescriptor } from kit.ArkData; import { filePreview } from kit.PreviewKit; import { FileUtil } from ./FileUtil; import { AppUtil } from ./AppUtil; import { WantUtil } from ./WantUtil;/*** 文件预览工具类* 提供文件预览、加载、判断等功能。…...

Windows 下实现 PHP 多版本动态切换管理(适配 phpStudy)+ 一键切换工具源码分享

&#x1f680; Windows 下实现 PHP 多版本动态切换管理&#xff08;适配 phpStudy&#xff09; 一键切换工具源码分享 &#x1f4e6; 工具特点&#x1f9ea; 效果展示&#x1f9f1; 环境要求&#x1f9d1;‍&#x1f4bb; 源码展示&#xff1a;php_switcher.py&#x1f6e0; 打…...

ReportLab 导出 PDF(图文表格)

ReportLab 导出 PDF&#xff08;文档创建&#xff09; ReportLab 导出 PDF&#xff08;页面布局&#xff09; ReportLab 导出 PDF&#xff08;图文表格) 文章目录 1. Paragraph&#xff08;段落&#xff09;2. Table&#xff08;表格&#xff09;3. VerticalBarChart&#xff0…...

【Kubernetes基础--Service深入理解】--查阅笔记4

目录 Service 的用法docker 对外提供服务service 对外提供服务 从集群外部访问 Pod 或 Service将容器应用的端口号映射到物理机将 Service 的端口号映射到物理机 Ingress&#xff1a;HTTP 7层路由机制创建Ingress Controller和默认的backend服务 k8s 通过创建 Service&#xff…...