接口类和抽象类在设计模式中的一些应用
C++设计模式中,有些模式需要使用接口类(Interface Class)和抽象类(Abstract Class)来实现特定的设计目标。以下是一些常见的设计模式及其需要的原因,并附上相应的代码片段。
1. 策略模式(Strategy Pattern)
需要接口类:策略模式通过定义一组算法或行为接口,使得算法可以独立于使用它们的客户端而变化。
原因:策略模式需要定义一组通用的行为接口,这些接口可以在运行时动态切换。
代码片段:
// 接口类
class Strategy {
public:virtual void execute() = 0; // 纯虚函数
};// 具体策略类
class ConcreteStrategyA : public Strategy {
public:void execute() override {std::cout << "Executing strategy A\n";}
};class ConcreteStrategyB : public Strategy {
public:void execute() override {std::cout << "Executing strategy B\n";}
};// 上下文类
class Context {
private:Strategy* strategy;public:Context(Strategy* s) : strategy(s) {}void setStrategy(Strategy* s) {strategy = s;}void executeStrategy() {strategy->execute();}
};// 使用策略模式
int main() {Context context(new ConcreteStrategyA());context.executeStrategy(); // 输出 "Executing strategy A"context.setStrategy(new ConcreteStrategyB());context.executeStrategy(); // 输出 "Executing strategy B"return 0;
}
2. 工厂方法模式(Factory Method Pattern)
需要抽象类:工厂方法模式通过定义一个创建对象的接口,但将具体类的实例化延迟到子类中。
原因:工厂方法模式需要定义一个抽象类,用于定义创建对象的接口,并让子类实现具体的产品创建逻辑。
代码片段:
// 抽象产品类
class Product {
public:virtual void use() = 0; // 纯虚函数
};// 具体产品类
class ConcreteProductA : public Product {
public:void use() override {std::cout << "Using product A\n";}
};class ConcreteProductB : public Product {
public:void use() override {std::cout << "Using product B\n";}
};// 抽象工厂类
class Creator {
public:virtual Product* factoryMethod() = 0; // 纯虚函数
};// 具体工厂类
class ConcreteCreatorA : public Creator {
public:Product* factoryMethod() override {return new ConcreteProductA();}
};class ConcreteCreatorB : public Creator {
public:Product* factoryMethod() override {return new ConcreteProductB();}
};// 使用工厂方法模式
int main() {Creator* creator = new ConcreteCreatorA();Product* product = creator->factoryMethod();product->use(); // 输出 "Using product A"creator = new ConcreteCreatorB();product = creator->factoryMethod();product->use(); // 输出 "Using product B"return 0;
}
3. 观察者模式(Observer Pattern)
需要接口类:观察者模式通过定义观察者和主题的接口,使得主题状态发生变化时,所有观察者都能得到通知。
原因:观察者模式需要定义通用的观察者和主题接口,以便在运行时动态添加和移除观察者。
代码片段:
// 接口类:观察者
class Observer {
public:virtual void update(int value) = 0; // 纯虚函数
};// 具体观察者类
class ConcreteObserverA : public Observer {
public:void update(int value) override {std::cout << "Observer A received update: " << value << "\n";}
};class ConcreteObserverB : public Observer {
public:void update(int value) override {std::cout << "Observer B received update: " << value << "\n";}
};// 主题类
class Subject {
private:std::vector<Observer*> observers;int state;public:void attach(Observer* observer) {observers.push_back(observer);}void setState(int value) {state = value;notifyObservers();}void notifyObservers() {for (Observer* observer : observers) {observer->update(state);}}
};// 使用观察者模式
int main() {Subject subject;ConcreteObserverA observerA;ConcreteObserverB observerB;subject.attach(&observerA);subject.attach(&observerB);subject.setState(10); // 输出 "Observer A received update: 10" 和 "Observer B received update: 10"return 0;
}
4. 模板方法模式(Template Method Pattern)
需要抽象类:模板方法模式通过定义一个算法的骨架,将某些步骤延迟到子类中实现。
原因:模板方法模式需要定义一个抽象类,用于定义算法的骨架,并让子类实现具体的步骤。
代码片段:
// 抽象类
class AbstractClass {
public:void templateMethod() {step1();step2();step3();}virtual void step1() = 0; // 纯虚函数virtual void step2() = 0; // 纯虚函数void step3() {std::cout << "Step 3 in AbstractClass\n";}
};// 具体子类
class ConcreteClassA : public AbstractClass {
public:void step1() override {std::cout << "Step 1 in ConcreteClassA\n";}void step2() override {std::cout << "Step 2 in ConcreteClassA\n";}
};class ConcreteClassB : public AbstractClass {
public:void step1() override {std::cout << "Step 1 in ConcreteClassB\n";}void step2() override {std::cout << "Step 2 in ConcreteClassB\n";}
};// 使用模板方法模式
int main() {AbstractClass* obj1 = new ConcreteClassA();AbstractClass* obj2 = new ConcreteClassB();obj1->templateMethod();// 输出 "Step 1 in ConcreteClassA"// 输出 "Step 2 in ConcreteClassA"// 输出 "Step 3 in AbstractClass"obj2->templateMethod();// 输出 "Step 1 in ConcreteClassB"// 输出 "Step 2 in ConcreteClassB"// 输出 "Step 3 in AbstractClass"delete obj1;delete obj2;return 0;
}
在C++设计模式中,命令模式(Command Pattern)、状态模式(State Pattern)、职责链模式(Chain of Responsibility Pattern)和组合模式(Composite Pattern)也都涉及使用接口类和抽象类来实现特定的设计目标。以下是对这些模式的详细说明,并附上相应的代码片段。
1. 命令模式(Command Pattern)
需要接口类:命令模式通过定义命令的接口,将请求封装为对象,使得可以参数化客户端对象、记录请求队列、支持撤销操作等。
原因:命令模式需要定义一个通用的命令接口,使得不同的命令对象可以被统一处理。
代码片段:
// 接口类:命令
class Command {
public:virtual void execute() = 0; // 纯虚函数
};// 具体命令类
class ConcreteCommandA : public Command {
private:std::string recipient;public:ConcreteCommandA(const std::string& r) : recipient(r) {}void execute() override {std::cout << "Command A executed by " << recipient << "\n";}
};class ConcreteCommandB : public Command {
private:std::string recipient;public:ConcreteCommandB(const std::string& r) : recipient(r) {}void execute() override {std::cout << "Command B executed by " << recipient << "\n";}
};// 调用者类
class Invoker {
private:Command* command;public:void setCommand(Command* c) {command = c;}void executeCommand() {command->execute();}
};// 使用命令模式
int main() {Invoker invoker;ConcreteCommandA commandA("Client A");ConcreteCommandB commandB("Client B");invoker.setCommand(&commandA);invoker.executeCommand(); // 输出 "Command A executed by Client A"invoker.setCommand(&commandB);invoker.executeCommand(); // 输出 "Command B executed by Client B"return 0;
}
2. 状态模式(State Pattern)
需要接口类:状态模式通过定义状态的接口,使得对象的行为可以根据其内部状态的改变而改变。
原因:状态模式需要定义一个通用的状态接口,使得不同的状态对象可以被统一处理。
代码片段:
// 接口类:状态
class State {
public:virtual void handle() = 0; // 纯虚函数
};// 具体状态类
class ConcreteStateA : public State {
public:void handle() override {std::cout << "Handling state A\n";}
};class ConcreteStateB : public State {
public:void handle() override {std::cout << "Handling state B\n";}
};// 上下文类
class Context {
private:State* state;public:void setState(State* s) {state = s;}void request() {state->handle();}
};// 使用状态模式
int main() {Context context;ConcreteStateA stateA;ConcreteStateB stateB;context.setState(&stateA);context.request(); // 输出 "Handling state A"context.setState(&stateB);context.request(); // 输出 "Handling state B"return 0;
}
3. 职责链模式(Chain of Responsibility Pattern)
需要接口类:职责链模式通过定义处理请求的接口,将多个处理者链接在一起,使得请求可以沿着链进行传递,直到被处理为止。
原因:职责链模式需要定义一个通用的处理者接口,使得不同的处理者可以被统一处理。
代码片段:
// 接口类:处理者
class Handler {
protected:Handler* next;public:void setNext(Handler* n) {next = n;}virtual void handleRequest(int request) = 0; // 纯虚函数
};// 具体处理者类
class ConcreteHandlerA : public Handler {
public:void handleRequest(int request) override {if (request < 10) {std::cout << "ConcreteHandlerA handled request " << request << "\n";} else if (next != nullptr) {next->handleRequest(request);}}
};class ConcreteHandlerB : public Handler {
public:void handleRequest(int request) override {if (request >= 10 && request < 20) {std::cout << "ConcreteHandlerB handled request " << request << "\n";} else if (next != nullptr) {next->handleRequest(request);}}
};// 使用职责链模式
int main() {ConcreteHandlerA handlerA;ConcreteHandlerB handlerB;handlerA.setNext(&handlerB);handlerA.handleRequest(5); // 输出 "ConcreteHandlerA handled request 5"handlerA.handleRequest(15); // 输出 "ConcreteHandlerB handled request 15"handlerA.handleRequest(25); // 没有处理者处理该请求return 0;
}
4. 组合模式(Composite Pattern)
需要抽象类:组合模式通过定义组合对象和叶子对象的接口,使得客户端可以统一处理单个对象和组合对象。
原因:组合模式需要定义一个通用的组件接口,使得叶子节点和组合节点可以被统一处理。
代码片段:
// 抽象类:组件
class Component {
public:virtual void operation() = 0; // 纯虚函数virtual void add(Component* component) {}virtual void remove(Component* component) {}virtual Component* getChild(int index) { return nullptr; }
};// 叶子类
class Leaf : public Component {
public:void operation() override {std::cout << "Leaf operation\n";}
};// 组合类
class Composite : public Component {
private:std::vector<Component*> children;public:void operation() override {std::cout << "Composite operation\n";for (Component* child : children) {child->operation();}}void add(Component* component) override {children.push_back(component);}void remove(Component* component) override {children.erase(std::remove(children.begin(), children.end(), component), children.end());}Component* getChild(int index) override {return children[index];}
};// 使用组合模式
int main() {Composite root;Leaf leaf1;Leaf leaf2;Composite branch;branch.add(&leaf1);branch.add(&leaf2);root.add(&branch);root.operation();// 输出 "Composite operation"// 输出 "Leaf operation"// 输出 "Leaf operation"return 0;
}
总结
- 策略模式:需要接口类来定义一组通用的行为接口。
- 工厂方法模式:需要抽象类来定义创建对象的接口,并让子类实现具体的产品创建逻辑。
- 观察者模式:需要接口类来定义观察者和主题的接口,以便在运行时动态添加和移除观察者。
- 模板方法模式:需要抽象类来定义算法的骨架,并让子类实现具体的步骤。
- 命令模式:需要接口类来定义命令的接口,使得可以参数化客户端对象、记录请求队列、支持撤销操作等。
- 状态模式:需要接口类来定义状态的接口,使得对象的行为可以根据其内部状态的改变而改变。
- 职责链模式:需要接口类来定义处理请求的接口,使得请求可以沿着链进行传递,直到被处理为止。
- 组合模式:需要抽象类来定义组合对象和叶子对象的接口,使得客户端可以统一处理单个对象和组合对象。
这些设计模式通过接口类和抽象类,提供了灵活的、可扩展的解决方案,有效地解决了软件设计中的常见问题。
相关文章:
接口类和抽象类在设计模式中的一些应用
C设计模式中,有些模式需要使用接口类(Interface Class)和抽象类(Abstract Class)来实现特定的设计目标。以下是一些常见的设计模式及其需要的原因,并附上相应的代码片段。 1. 策略模式(Strateg…...
【系统架构】如何演变系统架构:从单体到微服务
引言 随着企业的发展,网站架构必须不断演变以应对日益增长的用户流量和复杂性需求。本文将详细探讨从单体架构到微服务架构的演变过程,尤其关注订单和支付服务的实现方式,帮助您打造一个高效、可扩展的在线平台。 步骤1:分离应用…...
Neo4j入门:详解Cypher查询语言中的MATCH语句
Neo4j入门:详解Cypher查询语言中的MATCH语句 引言什么是MATCH语句?示例数据1. 基础节点查询查询所有节点按标签查询节点 2. 关系查询基础关系查询指定关系方向指定关系类型 3. 使用WHERE子句4. 使用参数5. 多重MATCH和WITH子句实用技巧总结 引言 大家好…...
CPP贪心算法示例
设有n个正整数(n ≤ 20),将它们联接成一排,组成一个最大的多位整数。 例如:n3时,3个整数13,312,343联接成的最大整数为:34331213 又如:n4时,4个整…...
GPT对NLP的冲击
让我来详细解释张俊林对GPT冲击NLP领域的分析: 中间任务(脚手架)的消失: 传统NLP中间任务: - 分词 - 词性标注 - 命名实体识别 - 句法分析 - 词向量学习为什么会消失: - GPT直接进行端到端学习 - 不需要人工定义的中间步骤 - 模…...
中值定理类证明题中对‘牛顿插值法’的应用
牛顿插值法是一种使用多项式插值的方法,它通过构造一个多项式来近似一组数据点。这种方法是由艾萨克牛顿提出的。牛顿插值法的一个优点是,当需要添加更多的数据点时,它不需要重新计算整个多项式,只需要对现有的多项式进行修改。...
HTMLCSS:3D 旋转卡片的炫酷动画
效果演示 这段代码是一个HTML和CSS的组合,用于创建一个具有3D效果的动画卡片。 HTML <div class"obj"><div class"objchild"><span class"inn6"><h3 class"text">我是谁?我在那<…...
Node.js 全栈开发进阶篇
🌈个人主页:前端青山 🔥系列专栏:node.js篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来node.js篇专栏内容:node.js- 全栈开发进阶篇 前言 大家好,我是青山。在上一篇文章中,…...
SQL语句-MySQL
数据定义声明 改变数据库语句 ALTER {DATABASE | SCHEMA} [db_name]alter_option ... ALTER {DATABASE | SCHEMA} db_nameUPGRADE DATA DIRECTORY NAMEalter_option: {[DEFAULT] CHARACTER SET [] charset_name| [DEFAULT] COLLATE [] collation_name } ALTER DATABASE使您能…...
Tencent Hunyuan3D
一、前言 腾讯于2024年11月5日正式开源了最新的MoE模型“混元Large”以及混元3D生成大模型“Hunyuan3D-1.0”,支持企业及开发者在精调、部署等不同场景下的使用需求。 GitHub - Tencent/Hunyuan3D-1 二、技术与原理 Hunyuan3D-1.0 是一款支持文本生成3D(…...
[ABC239E] Subtree K-th Max
[ABC239E] Subtree K-th Max 题面翻译 给定一棵 n n n 个节点的树,每个节点的权值为 x i x_i xi。 现有 Q Q Q 个询问,每个询问给定 v , k v,k v,k,求节点 v v v 的子树第 k k k 大的数。 0 ≤ x i ≤ 1 0 9 , 2 ≤ n ≤ 1 0 5 , …...
Axure设计之左右滚动组件教程(动态面板)
很多项目产品设计经常会遇到左右滚动的导航、图片展示、内容区域等,接下来我们用Axure来实现一下左右滚动的菜单导航。通过案例我们可以举一反三进行其他方式的滚动组件设计,如常见的上下滚动、翻页滚动等等。 一、效果展示: 1、点击“向左箭…...
善用Git LFS来降低模型文件对磁盘的占用
将讲一个实际的例子:对于模型文件,动辄就是好几个G,而有的仓库更是高达几十G,拉一个仓库到本地,稍不注意直接磁盘拉满都有可能。 比如:meta-llama-3.1-8b-instruct,拉到本地后发现居然占用了60G…...
Oracle RAC的thread
参考文档: Real Application Clusters Administration and Deployment Guide 3 Administering Database Instances and Cluster Databases Initialization Parameter Use in Oracle RAC Table 3-3 Initialization Parameters Specific to Oracle RAC THREAD Sp…...
如何创建备份设备以简化 SQL Server 备份过程?
SQL Server 中的备份设备是什么? 在 SQL Server 中,备份设备是用于存储备份数据的物理或逻辑介质。备份设备可以是文件、设备或其他存储介质。主要类型包括: 文件备份设备:通常是本地文件系统中的一个或多个文件。可以是 .bak 文…...
DeBiFormer实战:使用DeBiFormer实现图像分类任务(一)
摘要 一、论文介绍 研究背景:视觉Transformer在计算机视觉领域展现出巨大潜力,能够捕获长距离依赖关系,具有高并行性,有利于大型模型的训练和推理。现有问题:尽管大量研究设计了高效的注意力模式,但查询并…...
【go从零单排】迭代器(Iterators)
🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 语言中,迭代器的实现通常不是通过语言内置的迭代器类型&#x…...
Java与HTML:构建静态网页
在Web开发领域,HTML是构建网页的基础标记语言,而Java作为一种强大的编程语言,也能够在创建HTML内容方面发挥重要作用。今天,我们就来探讨一下如何使用Java来制作一个不那么简单的静态网页。 一、项目准备 首先,我们需…...
软件测试:测试用例详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、通用测试用例八要素 1、用例编号; 2、测试项目; 3、测试标题; 4、重要级别; 5、预置…...
FreeSWITCH Ubuntu 18.04 源码编译
应朋友邀请,试了试 FreeSWITCH Ubuntu 18.04 源码编译,交的作业如下: #!/bin/bash####### Ubuntu 18.04 LTS ####### ARM64 ####### FreeSWITCH 1.10.12apt update && \ apt install -y --fix-missing git sed bison build-essentia…...
保姆级教程:用Docker Compose一键部署带汉化和HTTPS的n8n,并配置反向代理(Nginx)
企业级n8n自动化平台全栈部署实战:从容器编排到安全加固 在数字化转型浪潮中,自动化工作流平台已成为企业降本增效的核心基础设施。n8n作为GitHub上增长最快的开源自动化工具之一,凭借其可视化编排能力和400节点生态,正在重塑企业…...
本地图片检索新方案:ImageSearch完全使用指南
本地图片检索新方案:ImageSearch完全使用指南 【免费下载链接】ImageSearch 基于.NET8的本地硬盘千万级图库以图搜图案例Demo和图片exif信息移除小工具分享 项目地址: https://gitcode.com/gh_mirrors/im/ImageSearch 当你的电脑中存储了成千上万张图片&…...
OpenClaw智能书签:用nanobot自动归类收藏网页内容
OpenClaw智能书签:用nanobot自动归类收藏网页内容 1. 为什么需要智能书签 作为一个每天要浏览大量技术文档和行业资讯的开发者,我发现自己陷入了"收藏即学会"的陷阱。Chrome书签栏里堆满了未分类的链接,Notion数据库里散落着零碎…...
从LLaVA到Stable Diffusion:多模态融合选拼接还是交叉注意力?一张图帮你做技术选型
多模态融合技术选型指南:拼接与交叉注意力的深度对比与实践策略 在构建现代多模态AI系统时,工程师们常常面临一个关键决策点:如何有效地融合来自不同模态的信息?想象一下,你正在开发一个智能医疗影像分析系统ÿ…...
C++的std--ranges算法自定义比较器与等价关系在集合操作中的运用
C20引入的std::ranges库为算法操作带来了革命性改进,其中自定义比较器与等价关系的灵活运用,显著提升了集合操作的表达能力。通过精确控制元素间的比较逻辑,开发者能够实现更复杂的业务需求,例如处理自定义对象集合或实现非标准排…...
【LAMMPS实战】从文献到模拟:精准定位与获取ReaxFF反应力场参数文件
1. 初识ReaxFF反应力场:为什么我们需要它? 第一次接触分子动力学模拟时,我完全被各种力场搞晕了。直到遇到需要模拟化学反应的情况,才发现普通的力场根本不够用。这时候ReaxFF反应力场就像救命稻草一样出现了。简单来说࿰…...
自动化立体仓库堆垛机设计(设计说明书+17张CAD图纸+开题报告+任务书+实习报告+中期检查报告+外文翻译)
自动化立体仓库堆垛机作为现代物流系统的核心设备,其设计需兼顾机械结构强度、运动控制精度与系统稳定性。该设计通过三维建模与力学仿真验证,确保堆垛机在高速运行时的结构可靠性,同时优化货叉伸缩机构与载货台升降导轨的配合间隙࿰…...
Python异步I/O终极调优手册(含strace+py-spy+asyncio debug mode三重追踪链路图)
第一章:Python异步I/O性能瓶颈的本质洞察Python的async/await语法虽大幅简化了异步编程模型,但其底层性能瓶颈并非源于语法糖本身,而根植于事件循环调度机制、GIL对CPU密集型任务的制约,以及I/O等待与协程切换之间的隐式开销。事件…...
轨迹规划实战:用多项式插值+粒子群玩转机械臂运动优化
轨迹规划 路径规划 matlab 353多项式插值 基于改进粒子群算法 时间最优 针对六自由度 四自由度都可以,轨迹规划,多项式插值,更改轨迹点位置就可以搞机器人轨迹规划最头疼的就是既要轨迹丝滑又要时间最短。今天咱们用Matlab整点狠活—…...
宁波小程序公司提供专业的小程序开发服务
在宁波小程序公司的服务中,我们致力于为客户提供清晰的内容结构和流畅的表达。我们通过深入的需求分析,确保每个项目都能符合客户特定的期望和市场需求。设计阶段注重市场调研,力求在视觉和功能上都能满足用户的使用习惯和偏好。开发过程中&a…...
