设计模式8-桥模式

设计模式8-Bridge 桥模式

  • 由来与目的
  • 模式定义
  • 结构
  • 代码推导
      • 1. 类和接口的定义
      • 2. 平台实现
      • 3. 业务抽象
      • 4. 使用示例
      • 总结
      • 1. 类数量过多,复杂度高
      • 2. 代码重复
      • 3. 不符合单一职责原则
      • 4. 缺乏扩展性
      • 改进后的设计
        • 1. 抽象和实现分离(桥接模式)
        • 2. 抽象类
        • 3. 使用装饰者模式添加功能
        • 4. 使用示例
      • 改进后的优点
    • 疑问
      • 1. `protected` 访问级别的意义
      • 2. `protected` 的使用场景
      • 具体分析代码中的选择
        • 1. `protected` 访问级别的好处
        • 2. 如果使用`private`
        • 3. 如果使用`public`
      • 总结
  • 要点总结

桥模式也属于单一职责模式中的一种。

由来与目的

桥模式的由来以及目的:由于某些类型的固有的实现逻辑使他们具有两个变化的维度乃至多个维度的变化。那么此时如何应对这种多维度的变化,如何利用面向对象技术?来使得类型可以轻松地沿着两个乃至多个方向进行变化,而不引入额外的复杂度呢?那么乔模式就应运而生,他的存在就是为了解决此类问题。

模式定义

将抽象部分也就是业务功能,与实现部分分离,使他们都可以独立的变化。

结构

在这里插入图片描述

代码推导

class Messager{
public:
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;

    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    
    virtual ~Messager(){}
};


//平台实现

class PCMessagerBase : public Messager{
public:
    
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};

class MobileMessagerBase : public Messager{
public:
    
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};



//业务抽象

class PCMessagerLite : public PCMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        PCMessagerBase::DrawShape();
        //........
    }
};



class PCMessagerPerfect : public PCMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::DrawShape();
        //........
    }
};


class MobileMessagerLite : public MobileMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        MobileMessagerBase::DrawShape();
        //........
    }
};


class MobileMessagerPerfect : public MobileMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::DrawShape();
        //........
    }
};


void Process(){
        //编译时装配
        Messager *m =
            new MobileMessagerPerfect();
}




这段代码实现了一个跨平台的消息传递系统,其中包含了多个层次的抽象和具体实现。它通过将平台相关的功能和业务逻辑分离来实现不同的消息传递方式。

1. 类和接口的定义

class Messager {
public:
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;

    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;
    
    virtual ~Messager() {}
};

Messager 是一个抽象基类,定义了登录、发送消息、发送图片以及平台相关的功能(播放声音、绘制图形、写文本、连接)。

2. 平台实现

class PCMessagerBase : public Messager {
public:
    virtual void PlaySound() {
        //**********
    }
    virtual void DrawShape() {
        //**********
    }
    virtual void WriteText() {
        //**********
    }
    virtual void Connect() {
        //**********
    }
};

class MobileMessagerBase : public Messager {
public:
    virtual void PlaySound() {
        //==========
    }
    virtual void DrawShape() {
        //==========
    }
    virtual void WriteText() {
        //==========
    }
    virtual void Connect() {
        //==========
    }
};

PCMessagerBaseMobileMessagerBase 是平台相关的具体实现类,分别实现了 PC 和移动平台上的功能。这两个类分别实现了播放声音、绘制图形、写文本和连接的方法。

3. 业务抽象

class PCMessagerLite : public PCMessagerBase {
public:
    virtual void Login(string username, string password) {
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message) {
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image) {
        PCMessagerBase::DrawShape();
        //........
    }
};

class PCMessagerPerfect : public PCMessagerBase {
public:
    virtual void Login(string username, string password) {
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message) {
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image) {
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::DrawShape();
        //........
    }
};

class MobileMessagerLite : public MobileMessagerBase {
public:
    virtual void Login(string username, string password) {
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message) {
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image) {
        MobileMessagerBase::DrawShape();
        //........
    }
};

class MobileMessagerPerfect : public MobileMessagerBase {
public:
    virtual void Login(string username, string password) {
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message) {
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image) {
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::DrawShape();
        //........
    }
};

这些类继承自平台实现类,并且在每个方法中调用了相应的基类方法,添加了业务逻辑。具体而言,PCMessagerLiteMobileMessagerLite 是简化版的实现,而 PCMessagerPerfectMobileMessagerPerfect 则是带有更多功能(如播放声音)的完整实现。

4. 使用示例

void Process() {
    //编译时装配
    Messager *m = new MobileMessagerPerfect();
}

Process 函数展示了如何创建一个 MobileMessagerPerfect 实例并赋值给 Messager 指针。

总结

这段代码通过将不同平台的实现和业务逻辑分开,展示了如何使用继承和多态来实现跨平台的消息传递系统。它遵循了开闭原则(对扩展开放,对修改关闭),使得添加新的平台或功能变得更容易。具体地,Messager 定义了接口,PCMessagerBaseMobileMessagerBase 实现了平台相关的功能,而 PCMessagerLitePCMessagerPerfectMobileMessagerLiteMobileMessagerPerfect 实现了具体的业务逻辑。

这段代码虽然展示了一个灵活的跨平台消息传递系统的设计,但仍然存在一些缺陷和改进空间。以下是一些主要的缺陷及其解决方案:

1. 类数量过多,复杂度高

缺陷:每添加一个新功能或新平台,都需要创建大量新的类,导致类数量爆炸,假设此时平台类数量为n ,平台实现功能类数量为m ,那么此时类的数量为1+n+m*n,增加了代码的复杂性和维护成本。
解决方案:可以使用桥接模式(Bridge Pattern),将抽象和实现分离,从而减少类的数量和复杂度。

2. 代码重复

缺陷:许多方法在不同类中有重复的实现,如 PlaySound()DrawShape()WriteText()Connect() 方法在不同类中基本相同。
解决方案:将这些方法提取到一个单独的类中,或者使用组合而不是继承来减少代码重复。

3. 不符合单一职责原则

缺陷Messager 类同时处理平台相关的实现和业务逻辑,违背了单一职责原则,使得类的职责不清晰。
解决方案:将平台相关的实现和业务逻辑分离,使用桥接模式或策略模式将这些职责分开。

4. 缺乏扩展性

缺陷:添加新功能(如加密、压缩等)需要创建大量新的类,缺乏灵活性。
解决方案:可以使用装饰者模式(Decorator Pattern)来动态地为对象添加职责,而不需要创建大量的子类。

改进后的设计

使用桥接模式和装饰者模式重新设计:

1. 抽象和实现分离(桥接模式)
class MessagerImp {
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;
    virtual ~MessagerImp() {}
};

class PCMessagerImp : public MessagerImp {
public:
    void PlaySound() override {
        // PC平台实现
    }
    void DrawShape() override {
        // PC平台实现
    }
    void WriteText() override {
        // PC平台实现
    }
    void Connect() override {
        // PC平台实现
    }
};

class MobileMessagerImp : public MessagerImp {
public:
    void PlaySound() override {
        // 移动平台实现
    }
    void DrawShape() override {
        // 移动平台实现
    }
    void WriteText() override {
        // 移动平台实现
    }
    void Connect() override {
        // 移动平台实现
    }
};
2. 抽象类
class Messager {
protected:
    MessagerImp* imp;
public:
    Messager(MessagerImp* imp) : imp(imp) {}
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;
    virtual ~Messager() {}
};

class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* imp) : Messager(imp) {}
    void Login(string username, string password) override {
        imp->Connect();
        // Lite版特有的登录逻辑
    }
    void SendMessage(string message) override {
        imp->WriteText();
        // Lite版特有的发送消息逻辑
    }
    void SendPicture(Image image) override {
        imp->DrawShape();
        // Lite版特有的发送图片逻辑
    }
};

class MessagerPerfect : public Messager {
public:
    MessagerPerfect(MessagerImp* imp) : Messager(imp) {}
    void Login(string username, string password) override {
        imp->PlaySound();
        imp->Connect();
        // Perfect版特有的登录逻辑
    }
    void SendMessage(string message) override {
        imp->PlaySound();
        imp->WriteText();
        // Perfect版特有的发送消息逻辑
    }
    void SendPicture(Image image) override {
        imp->PlaySound();
        imp->DrawShape();
        // Perfect版特有的发送图片逻辑
    }
};
3. 使用装饰者模式添加功能
class MessagerDecorator : public Messager {
protected:
    Messager* messager;
public:
    MessagerDecorator(Messager* messager) : Messager(messager->imp), messager(messager) {}
    void Login(string username, string password) override {
        messager->Login(username, password);
    }
    void SendMessage(string message) override {
        messager->SendMessage(message);
    }
    void SendPicture(Image image) override {
        messager->SendPicture(image);
    }
};

class EncryptedMessager : public MessagerDecorator {
public:
    EncryptedMessager(Messager* messager) : MessagerDecorator(messager) {}
    void Login(string username, string password) override {
        // 加密登录
        MessagerDecorator::Login(username, password);
    }
    void SendMessage(string message) override {
        // 加密消息
        MessagerDecorator::SendMessage(message);
    }
    void SendPicture(Image image) override {
        // 加密图片
        MessagerDecorator::SendPicture(image);
    }
};
4. 使用示例
void Process() {
    MessagerImp* pcImp = new PCMessagerImp();
    Messager* m = new EncryptedMessager(new MessagerPerfect(pcImp));
    m->Login("user", "password");
    m->SendMessage("Hello, World!");
    // Clean up
    delete m;
    delete pcImp;
}

改进后的优点

  1. 减少类数量:通过桥接模式,将平台相关实现和业务逻辑分离,减少了类的数量,此时类的数量为(1+n+m) < (1+n+m*n)。
  2. 减少代码重复:将公共方法提取到实现类中,减少了代码重复。
  3. 职责清晰:将平台相关实现和业务逻辑分离,符合单一职责原则。
  4. 增加扩展性:通过装饰者模式,能够动态地添加新功能,而无需创建大量新的子类。

通过这些改进,可以显著提高代码的可维护性、可扩展性和清晰性。

疑问

在面向对象编程中,选择成员变量的访问级别时,需要考虑类的设计和使用场景。在这段代码中,Messager类的imp成员变量被声明为protected,而不是private或者public,这是有特定原因的。

1. protected 访问级别的意义

protected 访问级别允许子类访问和修改基类中的成员变量,同时对类外部保持不可见。这样可以在保证类的封装性的同时,允许子类进行适当的扩展和修改。

2. protected 的使用场景

在这段代码中,Messager类的设计是为了作为一个基类,它的主要作用是定义接口和提供基础的实现,而具体的实现细节由其子类来完成。因此,将imp成员变量设为protected可以让子类方便地访问和操作这个变量,而无需通过公共接口来访问。

具体分析代码中的选择

1. protected 访问级别的好处
class Messager {
protected:
    MessagerImp* imp;
public:
    Messager(MessagerImp* imp) : imp(imp) {}
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;
    virtual ~Messager() {}
};

class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* imp) : Messager(imp) {}
    void Login(string username, string password) override {
        imp->Connect();
        // Lite版特有的登录逻辑
    }
    void SendMessage(string message) override {
        imp->WriteText();
        // Lite版特有的发送消息逻辑
    }
    void SendPicture(Image image) override {
        imp->DrawShape();
        // Lite版特有的发送图片逻辑
    }
};

在这种设计下,MessagerLite和其他子类可以直接访问imp,这使得子类可以轻松地调用平台相关的实现方法,如Connect()WriteText()DrawShape()

2. 如果使用private

如果将imp设为private,子类将无法直接访问imp,需要通过公共的getter和setter方法。这增加了额外的复杂性,而且在某些情况下可能会影响性能和代码的可读性。

class Messager {
private:
    MessagerImp* imp;
public:
    Messager(MessagerImp* imp) : imp(imp) {}
    MessagerImp* getImp() { return imp; }
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;
    virtual ~Messager() {}
};

class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* imp) : Messager(imp) {}
    void Login(string username, string password) override {
        getImp()->Connect();
        // Lite版特有的登录逻辑
    }
    void SendMessage(string message) override {
        getImp()->WriteText();
        // Lite版特有的发送消息逻辑
    }
    void SendPicture(Image image) override {
        getImp()->DrawShape();
        // Lite版特有的发送图片逻辑
    }
};
3. 如果使用public

如果将imp设为public,则任何外部代码都可以直接访问和修改imp,这违反了封装原则,容易导致错误和不必要的依赖。

class Messager {
public:
    MessagerImp* imp;
    Messager(MessagerImp* imp) : imp(imp) {}
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;
    virtual ~Messager() {}
};

// 外部代码可以直接访问 imp
Messager* m = new MessagerLite(new PCMessagerImp());
m->imp->Connect(); // 不推荐

总结

MessagerImp* imp设为protected是为了在保持封装性的同时,让子类能够方便地访问和使用该成员变量。这种设计既保证了基类和子类之间的良好协作,又避免了将实现细节暴露给类的外部,提高了代码的可维护性和扩展性。

要点总结

  • 模式使用对象间的组合关系解耦合了。抽象和现实之间固有的绑定关系,使得抽象可实现可以沿着各自的维度来变化所,所谓抽象和实现沿着各自维度的变化,即子类化他们
  • 强模式有时候类似于多继承方案。但是多继承方案往往违背单一职责,原则即一个类只有一个变化的原因,复用性比较差。桥模式是比多继承方案更好的解决方法。
  • 乔模桥模式的应用一般在两个非常强的变化维度,有时一个内页。有。多于两个的变化维度,这时可以使用桥的扩展模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/791501.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

本地部署,GFPGAN: 实用的面部修复算法

目录 什么是 GFPGAN&#xff1f; 技术原理 主要功能 应用场景 本地安装 运行结果 结语 Tip&#xff1a; 在图像处理和计算机视觉领域&#xff0c;面部修复是一个重要且具有挑战性的研究方向。随着深度学习技术的不断进步&#xff0c;许多新的算法被提出&#xff0c;用于…

基于JavaSpringBoot+Vue+uniapp微信小程序校园宿舍管理系统设计与实现(7000字论文参考+源码+LW+部署讲解)

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

打包时提示:Missing Gradle Project Information.或者在加载gradle时出错

1.Android打包弹出错误提示框&#xff1a;missing gradle project information. please check if the IDE successfully synchronized its state with the Gradble project model. 2.加载gradle出错&#xff1a;修复报错后 File -> Sync Project with Gradle Files

【DevOps】在云原生时代的角色与重要性探索

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是云原生 2、云原生的核心特性 3、什么是DevOps…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 找单词(200分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

javaweb图书商城系统带万字文档网上书城java项目java课程设计java毕业设计

文章目录 图书商城系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 图书商城系统 一、项目演示 网上书城 二、项目介绍 语言&#xff1a;java 数据库&#xff1a;…

vue2+Dexie.js基本使用——前端大容量存储IndexedDB 的包装库

文章目录 IndexedDB存储IndexedDB常用概念Dexie.js操作流程获取一个数据库实例定义对象存储空间和索引等数据库结构_基本增删查改 IndexedDB 是一个事务型数据库系统&#xff0c;类似于基于 SQL 的 RDBMS。然而&#xff0c;不像 RDBMS 使用固定列表&#xff0c;IndexedDB 是一个…

数据结构 —— BellmanFord算法

数据结构 —— BellmanFord算法 BellmanFord算法检测负权值环BellmanFord和Dijkstra思想上的区别Dijkstra算法的思想Bellman-Ford算法的思想思想上的对比 我们今天来看一个算法BellmanFord算法&#xff0c;我们之前的Dijkstra算法只能用来解决正权图的单源最短路径问题。 Bell…

linux_进程概念——理解冯诺依曼体系结构

前言&#xff1a; 本篇内容是为了让友友们较好地理解进程的概念&#xff0c; 而在真正了解进行概念之前&#xff0c; 要先了解一下冯诺依曼体系结构。 所以博主会先对冯诺伊曼体系结构进行解释&#xff0c; 然后再讲解进程的概念。 ps&#xff1a; 本篇内容适合了解一些linux指…

新兴市场游戏产业爆发 传音以技术抢抓机遇 ​

随着年轻人口的增加以及互联网的普及,非洲、中东等新兴市场正迎来游戏产业的大爆发,吸引着全球游戏企业玩家在此开疆辟土。中国出海企业代表传音以新兴市场需求为中心,秉持本地化创新理念不断加强游戏等关键领域技术攻关凭借移动终端设备为全球玩家带来极致游戏体验,收获了消费…

变位齿轮的齿高好像不变

通过这个软件的计算&#xff0c;变位尺寸的大小径都会同时变化&#xff0c;从而整个齿高好像没有变化。 下面百度答案

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《计及负荷时空特性的高速公路链式微网光-储-充容量优化配置方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

【C++报错已解决】Invalid Use of Incomplete Type

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;完整类型定义2.2 方法二…

【云岚到家】-day05-4-项目迁移-商品搜索

【云岚到家】-day05-4-项目迁移-商品搜索 2 项目迁移-商品搜索2.1 迁移目标2.2 能力基础2.2.1 索引同步方案设计能力2.2.2 Elasticsearch全文检索应用能力 2.3 需求分析2.3.1 界面原型2.3.2 功能列表梳理 2.4 系统设计2.4.1 索引结构2.4.2 索引同步方案2.4.3 搜索自动补全2.4.4…

Java---数组

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 前言 无论c语言还是java数组都是重中之重&#xff0…

解决keil调试遇到的hardlfault问题

在程序开发过程中遇到的程序死机问题 导致死机的原因&#xff1a;内存溢出&#xff0c;堆栈溢出&#xff0c;数组越界&#xff0c;中断错误。。。。。。 出现这个问题&#xff0c;首先查看线程的调度关系 看最后是在哪个位置死机&#xff0c;如果rt_current_thread在main_thre…

视图库对接系列(GA-T 1400)十五、视图库对接系列(本级)删除、取消订阅

说明 之前说了订阅和修改订阅,今天我们来实现删除和取消订阅二个接口。删除订阅 逻辑: 请求下级的接口成功我们就删除数据库的对应数据视图库接口定义 实现 service接口层 //删除订阅ResponseStatusListModeObject deleteSubscribes(String idList, HttpServletRequest re…

MongoDB - 集合和文档的增删改查操作

文章目录 1. MongoDB 运行命令2. MongoDB CRUD操作1. 新增文档1. 新增单个文档 insertOne2. 批量新增文档 insertMany 2. 查询文档1. 查询所有文档2. 指定相等条件3. 使用查询操作符指定条件4. 指定逻辑操作符 (AND / OR) 3. 更新文档1. 更新操作符语法2. 更新单个文档 updateO…

土壤分析仪:解密土壤之奥秘的科技先锋

在农业生产和生态保护的道路上&#xff0c;土壤的质量与状况一直是我们关注的焦点。土壤分析仪&#xff0c;作为现代科技在农业和环保领域的杰出代表&#xff0c;以其高效、精准的分析能力&#xff0c;为我们揭示了土壤的奥秘&#xff0c;为农业生产提供了科学指导&#xff0c;…

(Windows环境)FFMPEG编译,包含编译x264以及x265

本文使用 MSYS2 来编译 ffmpeg 一、安装MSYS2 MSYS2 是 Windows 下的一组编译套件&#xff0c;它可以在 Windows 系统中模拟 Linux 下的编译环境&#xff0c;如使用 shell 运行命令、使用 pacman 安装软件包、使用 gcc (MinGW) 编译代码等。 MSYS2 的安装也非常省心&#x…