设计模式——单一职责模式之桥模式

news2024/11/23 13:45:10

文章目录

  • 前言
  • 一、“单一职责” 模式
  • 二、Bridge 桥模式
    • 1、动机
    • 2、模式定义
    • 3、伪代码示例
    • 4、结构
  • 总结


前言


一、“单一职责” 模式

  • 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
  • 典型模式
    • Decorator
    • Bridge

二、Bridge 桥模式

1、动机

  • 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。
  • 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?

2、模式定义

抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。

3、伪代码示例

bridge1.cpp

//bridge1.cpp
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(){}
};
 
 
//平台实现 n
//类的数目:1 + n + m * n
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();
}

基于装饰模式的经验,将业务的继承修改为组合,进行如下的修改:

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(){}
};
 
//平台实现 n
//类的数目:1 + n + m * n
//主要到这个类里只实现了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(){
        //==========
    }
};
 
 
//业务抽象 
//主要到这个类里只需要实现了Messager这个类的部分接口,如果继承Messager是不合适的
class MessagerLite {
    Messager* messager; //指针才具有多态性
public:
    virtual void Login(string username, string password){
        
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        messager->DrawShape();
        //........
    }
};
 
 
class MessagerPerfect {
    Messager* messager;
public:
    
    virtual void Login(string username, string password){
        messager->PlaySound();
        //********
        messager->Connect();
        //........
    }
    
    virtual void SendMessage(string message){
        
        messager->PlaySound();
        //********
        messager->WriteText();
        //........
    }
    
    virtual void SendPicture(Image image){
        
        messager->PlaySound();
        //********
        messager->DrawShape();
        //........
    }
};
 
void Process(){
    //编译时装配
    Messager *m = new MobileMessagerPerfect();
}

PCMessageBase 类和 MessagerLite、MessagerPerfect 类都各自只实现了 Messager 的部分接口,说明 Messager 中的两部分的接口不应该放到一起,应该进行拆分:

bridge2.cpp

//bridge2.cpp
class Messager{
protected:
     MessagerImp* messagerImp;// MessagerImp
public:
    Messager(MessagerImpl* mimp) : messagerImpl(mimp) { }
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;
    
    virtual ~Messager(){}
};
 
class MessagerImp{
public:
    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    
    virtual ~MessagerImp(){}
};
 
 
//平台实现 n
class PCMessagerImp : public MessagerImp{
public:
    
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};
 
class MobileMessagerImp : public MessagerImp{
public:
    
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};
 
//业务抽象 m
//类的数目:1+n+m
class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* mimp) : Messager(mimp) { 
        
    }
    virtual void Login(string username, string password){
        
        messagerImp->Connect(); //messagerImpl字段在父类中声明了
        //........
    }
    virtual void SendMessage(string message){
        
        messagerImp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        messagerImp->DrawShape();
        //........
    }
};
 
 
class MessagerPerfect  :public Messager {
public: 
    MessagerPerfect(MessagerImp* mimp) : Messager(mimp) { 
        
    }
    virtual void Login(string username, string password){
        
        messagerImp->PlaySound();
        //********
        messagerImp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        messagerImp->PlaySound();
        //********
        messagerImp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        messagerImp->PlaySound();
        //********
        messagerImp->DrawShape();
        //........
    }
};
 
void Process(){
    //运行时装配
    MessagerImp* mImp = new PCMessagerImp();
    Messager *m = new MessagerPerfect(mImp);
}

4、结构

在这里插入图片描述

【注】:

  • Abstraction -> Messgaer (稳定) 【imp对应到代码中就是 Messager 中有一个MessagerImpl类型的指针变量】
  • Implementor -> MessagerImpl (稳定
  • RefinedAbstraction -> MessagerLite / MessagerPerfect (变化)
  • ConcreteImplementorX -> XXMessagerImpl (变化)

两个方向独立变化,而不是杂糅在一起。


总结

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

我的qq:2442391036,欢迎交流!


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++STL】map/set源码封装简单分析

文章目录 一. 问题的抛出二. 红黑树的实现三. map/set实现四. 分析五. KeyOfValue仿函数结束语 一. 问题的抛出 我们知道C的STL中map和set的底层都是红黑树。 但是仔细思考一下,map是存储键值对,也就是Key_Value模型 而set是Key的模型 那么STL中的红黑树…

apisdk-starter自动装配的思路与应用

apisdk-starter整体思路 首先定义开发者定义的开放接口声明为原始类,javassist生成的类是增强类。 使用springboot的EnableAutoConfiguration和Import触发Spring扫描组件扫描原始类,得到所有BeanDefinition拓展FactoryBean,构造函数的参数为…

力扣算题Day20

98.验证二叉搜索树(了解二叉树的性质,才是编写此道题代码的基础) 做题伤着了:这道题我做的时候,看到别人写的代码很长,懒得看,直接干。自己编写代码,没有了解平衡二叉树的性质,然后出现了下图[0,-1]、[0]的…

落地页设计的营销心理学(一)

营销落地页的作用,是为了促进目标用户转化。但如何提升转化率,这就需要我们了解用户在浏览落地页行为背后的动机、心理活动是什么,才能更好地制定营销策略。 营销心理学是指应用心理学原理来解释、预测和影响人们购买决策的一门学科。在落地页…

Goby 漏洞更新 |华视私云-CDN直播加速服务器默认口令漏洞

漏洞名称:华视私云-CDN直播加速服务器默认口令漏洞 English Name:Sinovision Cloud CDN live default passwd CVSS core: 6.5 影响资产数:737 漏洞描述: 华视私云-CDN直播加速服务器是一款用于CDN直播加速的服务器。华视私云…

Restormer Efficient Transformer for High-Resolution Image Restoration论文代码运行记录

文章目录 Restormer代码训练和测试运行记录文章及代码地址1. 所需环境2. 配置环境3. 安装gdrive以便下载数据集4. 放置权重文件5. 运行Demo运行单图像散焦去模糊训练、测试 Restormer代码训练和测试运行记录 文章及代码地址 文章名称:Restormer: Efficient Transf…

获取cookies的方法及使用postman进行接口关联

第一种获取cookies的方式 看有没有专门的登录测试地址,访问来获取cookie信息,然后将cookie信息粘贴到header里面 第二种获取cookies的方式 在登录前,提前打开审查元素,然后输入账号密码后,点击登录,就可…

刚来起薪就18K,公司刚来的00后真是卷王....

都说00后躺平了,但是有一说一,该卷的还是卷。 这不,前段时间我们公司来了个00后,工作都没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了…

【Java零基础入门篇】第 ⑤ 期 - 抽象类和接口(一)

博主:命运之光 专栏:JAVA入门 学习目标 1.了解什么是抽象类,什么是接口; 2.掌握抽象类和接口的定义方法; 3.理解接口和抽象类的使用场景; 4.掌握多态的含义和用法; 5.掌握内部类的定义方法和使用…

数字孪生应用 | 3D可视化技术助力智慧煤矿建设,提升煤矿生产效率

智慧煤矿数字孪生可视化平台是一种利用现代信息技术手段,对煤矿的生产过程进行实时监测、管理和控制的系统。它能够将煤矿内的数据、信息、图像等多种信息整合在一起,通过3D可视化的方式呈现给煤矿管理者和工作人员,帮助他们更好地了解煤矿的…

mysql读写分离实验

amoeba服务器 mkder amoeba tar xf amoba- mysql-binary-2. 2.0.tar.gz -C amoeba mv amoeba /usr/local 解压jdk mv jdk1.6 /usr/local/jdk1.6 vim /etc/profile export JAVA_home/usr/local/jdk1.6 export CLASSPATH.:$JAVA_HOME/lib:$JAVE_HOME/jre/lib export AM…

SpringBoot+myBatis(plus)+MySQL+VUE最基础简易的前后端全栈demo制作

网站全栈制作: 一:后端 为了跟公司后端更好的扯皮(不是),本人决定学一下java语言的后端接口书写。 项目制作:后端采用SpringBootmyBatis(plus)mysql(IDE为IDEA软件)。前端采用Vue…

奶爸式Swagger教学

目录 一、导入依赖 二、SwaggerConfig基础编程 三、Swagger 常用说明注解 1.API 2.ApiOperation 3.ApiModel 4.ApiModelProperty 5.ApiParam 6.ApilmplicitParam 一、导入依赖 <!--开启Swagger --><!-- https://mvnrepository.com/artifact/io.springf…

自动化测试框架搭建步骤教程

说起自动化测试&#xff0c;我想大家都会有个疑问&#xff0c;要不要做自动化测试&#xff1f; 自动化测试给我们带来的收益是否会超出在建设时所投入的成本&#xff0c;这个嘛别说是我&#xff0c;即便是高手也很难回答&#xff0c;自动化测试的初衷是美好的&#xff0c;而测试…

实验1 流水线及流水线中的冲突【计算机系统结构】

实验1 流水线及流水线中的冲突【计算机系统结构】 前言推荐实验1 流水线及流水线中的冲突1 实验目的2 实验平台3 实验内容和步骤4 实验结论5 实验心得 最后 前言 2023-5-12 20:22:09 以下内容源自《【计算机系统结构】》 仅供学习交流使用 推荐 无 实验1 流水线及流水线中…

【国际知名-hacker`动态`】洞悉-最新 hacker技术 新闻

国际知名-黑客动态 1、【导读】黑客 最新 技术&新闻 平台 2、【动态】每日必看的朋友圈 3、【多看看】跳出舒适圈&#xff0c;你要学的还有很多 ​ The Hacker News 报道黑客攻击、网络安全、科技新闻&#xff08;内容深入浅出>提供及时、可靠的信息) 链接&#xff1a…

面板数据的门槛|门限效应检验、阈值确定、回归结果解释

写在前面 up学习是参照一个B站大美女&#xff1a;传送门 这里做笔记总结&#xff0c;勿cue 1.为什么是门槛模型 这玩意是针对非线性的举个例子 打LOL&#xff0c;最开始接触的时候&#xff0c;是新手训练营&#xff0c;你需要画大量的时间去学习如何行走、控制角色、熟悉英雄…

使用 Selenium IDE 上手 web 自动化测试

安装 Selenium IDE 是以浏览器插件的形式使用的&#xff0c;主要包含 FireFox 和 Chrome 两种。安装方式分为&#xff1a; 在线安装&#xff1a;下载对应的浏览器插件&#xff08;chrome)。本地安装&#xff1a;把 .zip 压缩包拖到浏览器的扩展页面。 开始页面 在浏览器的插…

patchelf 和 glibc-all-in-one

小白垃圾笔记。不建议阅读。 为什么突然学这个呢&#xff1f; 因为因为因为一个栈溢出题&#xff0c;把我的ubuntu16搞崩了。具体是什么原因呢。 我很菜&#xff0c;我不知道pip是干啥的&#xff0c;之前装pwntools都是直接粘贴命令。然而这次&#xff0c;ubuntu16的python其…

冠珠瓷砖打造民族文化品牌,让中国陶成为中国潮

随着国家经济实力、综合国力的大幅度提升&#xff0c;文化自信被强势唤醒&#xff0c;“国潮”之风蔚然复兴。“讲好中国故事、传递中国文化”&#xff0c;成为民族品牌共同的愿景。冠珠瓷砖在建立之初就立足于民族品牌的打造&#xff0c;致力于“砖筑中国瓷砖硬实力”&#xf…