首页 > 其他分享 >c/c+设计模式--桥接模式

c/c+设计模式--桥接模式

时间:2024-05-29 14:44:44浏览次数:14  
标签:桥接 模式 -- ImageOS 抽象 jpg 设计模式 实现

桥接模式是软件设计模式的一种,它用于将抽象部分与其实现部分分离,使它们可以独立变化。这种模式通过创建桥接接口,将抽象和实现部分分离,从而使它们可以独立地变化,而不会相互影响。

在桥接模式中,有两个重要的概念:抽象和实现。抽象定义了客户端的接口,而实现则提供了具体的实现。通过桥接模式,抽象和实现可以独立地进行扩展,而不会相互影响。这种分离允许系统更容易地适应变化,并且提供了更大的灵活性。

桥接模式通常用于以下情况:

  • 当需要避免由于抽象和实现之间的紧耦合而导致的继承层次结构爆炸时。
  • 当抽象和实现部分需要独立扩展而不会相互影响时。
  • 当一个类存在多个独立变化的维度时,可以使用桥接模式将它们分离,以便各自独立变化。

在实际应用中,桥接模式可以被用来处理数据库驱动程序、操作系统封装、图形用户界面等领域,以便将抽象部分和实现部分分离,使它们可以独立变化。

总的来说,桥接模式是一种有助于解耦抽象和实现的设计模式,它提供了更大的灵活性和可维护性,特别适用于需要处理多个独立变化维度的情况。

namespace _nmsp1
{
    
    //图像显示类
    class Image
    {
    public:
        //根据pData(缓冲区)中的内容以及iDataLen所指示的缓冲区的长度,将这些数据显示出来
        void draw(const char* pfilename)
        {
            int iLen = 0;
            char* pData = parsefile(pfilename, iLen);
            if (iLen > 0)
            {
                cout << "显示pData所指向的缓冲区中的图像数据。" << endl;
                //....
                delete pData; //模拟代码中因为pData的内存是new出来的,所以这里需要释放该内存
            }
        }
        virtual ~Image() {} //做父类时析构函数应该为虚函数
    private:
        //根据文件名分析文件内容,每个子类因为图像文件格式不同,会有不同的读取和处理代码
        virtual char* parsefile(const char* pfilename, int& iLen) = 0;
    };

    //处理png格式图像文件的显示
    class Image_png :public Image
    {
    private:
        //读取png文件内容并进行解析,最终整理成统一的二进制数据格式返回
        virtual char* parsefile(const char* pfilename, int& iLen)
        {
            //以下是模拟代码,模拟从图像文件中读取到了数据,最终转换成了100个字节的数据格式(事先约定好的格式规范)并返回
            cout << "开始分析png文件中的数据并将分析结果放到pData中。";
            iLen = 100;
            char* presult = new char[iLen];
            //...
            return presult;
        }
    };
    //处理jpg格式图像文件的显示
    class Image_jpg :public Image
    {
    private:
        virtual char* parsefile(const char* pfilename, int& iLen)
        {
            cout << "开始分析jpg文件中的数据并将分析结果放到pData中。";
            //......
        }
    };
    //处理jpg格式图像文件的显示
    class Image_bmp :public Image
    {
    private:
        virtual char* parsefile(const char* pfilename, int& iLen)
        {
            cout << "开始分析bmp文件中的数据并将分析结果放到pData中。";
            //......
        }
    };
}
int main()
{

      _nmsp1::Image* pImg = new _nmsp1::Image_png();
    pImg->draw("c:\\somedir\\filename.jpg");

    //释放资源
    delete pImg;
}

 

 

namespace _nmsp2
{
    //操作系统类型相关类
    class ImageOS
    {
    public:
        virtual void draw(char* pData, int iLen) = 0;
        virtual ~ImageOS() {} //做父类时析构函数应该为虚函数
    };
    //Windows操作系统
    class ImageOS_Windows :public ImageOS
    {
    public:
        virtual void draw(char* pData, int iLen)
        {
            cout << "在Windows操作系统下显示pData所指向的缓冲区中的图像数据。" << endl;
            //...具体处理代码略
        }
    };
    //Linux操作系统
    class ImageOS_Linux :public ImageOS
    {
    public:
        virtual void draw(char* pData, int iLen)
        {
            cout << "在Linux操作系统下显示pData所指向的缓冲区中的图像数据。" << endl;
            //...具体处理代码略
        }
    };
    //Mac操作系统
    class ImageOS_Mac :public ImageOS
    {
    public:
        virtual void draw(char* pData, int iLen)
        {
            cout << "在Mac操作系统下显示pData所指向的缓冲区中的图像数据。" << endl;
            //...具体处理代码略
        }
    };
    //----------------------------
    //图像文件格式相关类
    class ImageFormat
    {
    public:
        ImageFormat(ImageOS* pimgos) :m_pImgOS(pimgos) {} //构造函数
        virtual void parsefile(const char* pfilename) = 0; //根据文件名分析文件内容,每个子类因为图像文件格式不同,会有不同的读取和处理代码
        virtual ~ImageFormat() {} //做父类时析构函数应该为虚函数
    protected:
        ImageOS* m_pImgOS; //委托
    };
    //png格式的图像文件
    class Image_png :public ImageFormat
    {
    public:
        Image_png(ImageOS* pimgos) :ImageFormat(pimgos) {} //构造函数
        virtual void parsefile(const char* pfilename)
        {
            cout << "开始分析png文件中的数据并将分析结果放到pData中。";
            int iLen = 100;
            char* presult = new char[iLen];
            m_pImgOS->draw(presult, iLen);

            //释放资源
            delete presult;
        }
    };
    //jpg格式的图像文件
    class Image_jpg :public ImageFormat
    {
    public:
        Image_jpg(ImageOS* pimgos) :ImageFormat(pimgos) {} //构造函数
        virtual void parsefile(const char* pfilename)
        {
            cout << "开始分析jpg文件中的数据并将分析结果放到pData中。";
            //......            
        }
    };
    //bmp格式的图像文件
    class Image_bmp :public ImageFormat
    {
    public:
        Image_bmp(ImageOS* pimgos) :ImageFormat(pimgos) {} //构造函数
        virtual void parsefile(const char* pfilename)
        {
            cout << "开始分析bmp文件中的数据并将分析结果放到pData中。";
            //......            
        }
    };
}

int main()
{
 _nmsp2::ImageOS* pimgos_windows = new _nmsp2::ImageOS_Windows(); //针对Windows操作系统
    _nmsp2::ImageFormat* pimg_png = new _nmsp2::Image_png(pimgos_windows); //运行时把图像文件格式png和操作系统windows动态组合到一起。
    pimg_png->parsefile("c:\\somedir\\filename.jpg");

    //释放资源
    delete pimg_png;
    delete pimgos_windows;
    
    return 0;


}

桥接模式uml:

 桥接(Bridge)模式:桥梁模式(桥模式),结构型模式。     //解决的问题:根据单一职责原则,在一个类中,不要做太多事情,如果事情很多,尽量拆分到多个类中去,然后在       //一个类中包含指向另外一个类对象的指针,当需要执行另外一个类中的动作时,用指针直接去调用另外一个类的成员函数。    (1)一个传统的继承范例导致子类数量爆炸式增长     //图像文件格式:png,jpg,bmp等
 (2)将类与类之间的继承关系改为委托关系     //类与类之间:继承、组合(委托);     //文件格式:png、jpg、bmp。 操作系统类型:Windows、Linux、Mac。     //说明:a)parsefile()其实现代码与具体操作系统类型无关。  b):draw():不同的操作系统,用于显示pData的实现代码不同。
  (3)引入桥接(Bridge)模式     //不同维度的独立变化,才是能够顺利使用桥接模式的前提。     //定义:将抽象部分与它的实现部分分离,使他们都可以独立地变化和扩展。     //a)抽象部分:一般指业务功能,比如ImageFormat类。     //b)实现部分:一般指具体平台实现,比如ImageOS类。     //角色     //(a)Abstraction(抽象部分相关接口):ImageFormat类     //(b)RefinedAbstraction(扩充抽象部分接口):Image_png、Image_jpg、Image_bmp类。     //(c)Implementor(实现部分相关接口):ImageOS类     //(d)ConcreteImplementor(实现部分具体类):ImageOS_Windows、ImageOS_Linux、ImageOS_Mac类。     //单一职责原则,开闭原则,组合复用原则,依赖倒置原则。  

 

 

 

标签:桥接,模式,--,ImageOS,抽象,jpg,设计模式,实现
From: https://www.cnblogs.com/bwbfight/p/18220262

相关文章

  • css通过子元素选择父元素的实现示例
    在CSS中,直接通过子元素选择其父元素并不直接支持,因为CSS的选择器是从上到下(从父元素到子元素)进行选择的,而不是相反。但是,你可以使用其他方法或技术来间接实现这一效果,比如使用JavaScript、jQuery或其他脚本语言,或者通过调整你的HTML结构和CSS样式来达到类似的效果。不过,我可以给......
  • Go--生成excel表格,循环赋值并避免重复项
    先下载第三方依赖包:goget-ugithub.com/xuri/excelize/v2 假设原数据格式为:typeDatastruct{PsastringGroupstringOperatorstring} 将数据插入新生成的execl表格中,并且当group值相同时,只更新该group的operator值,即最终数据中,group没有......
  • esp32-s3-mini-1 otg board, uvc调试记录
    网上购买了一块ESP32-S3-USB-OTG开发板(非乐鑫官方开发板)。准备实现usbuvccamera+lcd显示。使用esp-idf/example/usb/host/uvc进行测试,修改了引脚,对USB供电和数据切换的引脚重新校正,出现报错:0x40056fc9:memcpyinROM0x4200b219:_uvc_process_payloadatC:/Users/yinsu......
  • __dirname is not defined in ES module scope
    在package.json中的type=module的项目中,我创建了一个ts文件,类型是esm的类型。这里的报错是因为我们错误的使用了module的语法到esm的文件中,要解决这个问题的方法有两种,第一种改为module,另一种是改为esm的写法。首先是第一种改为module的写法,那就是把import改为require,然后由于......
  • 从 .NET 到 C++:集合处理的思考
    1.IEnumerable与List的比较在.NET中,IEnumerable和List是两种常用的集合类型,它们有各自的适用场景:IEnumerable<T>:优点:惰性求值,仅在迭代时计算,适用于大数据集或流式数据处理。缺点:不能进行索引访问,没有直接的添加或移除元素的方法。List<T>:优点:支持索引访问,具备......
  • stm8系列--可变频率PWM输出
     PA3STM8S003F3timer2_init();//初始化#definePUL_COUNT4000voidtimer2_init(void){TIM2_DeInit();TIM2_TimeBaseInit(TIM2_PRESCALER_8,PUL_COUNT-1);//62.5HZ2M/8/4000=62.5HZ1个数4usTIM2_OC3Init(TIM2_OCMODE_PWM1,TIM2_OUTPUTS......
  • ChatGPT随笔
    我通过询问周边数位每天使用大模型平均超过两个小时以上的学者,得到他们对于大模型的看法是:“ChatGPT确实很厉害,但是价格难以负担,且使用十分不便。国产的也有用,但是没大用,更多像个高级搜索引擎”。进一步问他们平时最多用大模型做什么,答案基本是:“进行文本翻译、润色文本、生成简单......
  • 天池O2O优惠券使用预测相关学习
    学习网址:https://blog.csdn.net/zimiao552147572/article/details/105940961等1、Data.rename(columns={'col1':'rename_col1'},inplace=True),可以看到col1被重命名为rename_col1,inplace=True表示在原数据进行修改。2、(date()-date()).days()可以是负值吗?应该是可以的3、t、......
  • Centos7 双网卡配置(Nat+hostonly)
    双网卡配置上网异常分析发现内网网段之间可以正常ping通,但却无法连接外网。经过一翻查看分析,是由于多网卡默认启用自动路由引起冲突问题发现背景虚拟机上网,固定静态IP(hostonly模式),在copy虚拟机时候不用管nat或者桥接IP,使用shell直接ssh静态IP访问一、网卡配置cat......
  • 如何批量新建文件夹并命名?3个实用文件重命名技巧请收藏
    如何批量新建文件夹并命名?很多从事文职类工作的小伙伴们应该都会在工作中会遇到关于文件夹批量新建的问题,面对需要新建几百个文件夹还在一个一个手动操作的话,这样的话太影响工作效率了,这里小编就来给大家分享几个批量新建文件夹并命名的方法,希望可以通过这篇文章帮助到你,以后再......