本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7699301.html,记录一下学习过程以备后续查用。

一、引言

今天我们要讲结构型设计模式的第二个模式--桥接模式,也有叫桥模式的。桥在我们现实生活中经常是连接着A地和B地,再往后来发展,桥引申为一种纽

带,比如,丝绸之路是连接亚洲和欧洲的桥梁。有了桥,我们出行更方便了,不需要绕路或搭船。针对桥的使用环境来说,桥解决了跨越和衔接的问题。在

设计模式中的桥接模式也有类似的概念,是连接了两个不同维度的东西,而且这两个维度又有强烈的变化。

二、桥接模式介绍

桥接模式:英文名称--Bridge Pattern;分类--结构型。

2.1、动机(Motivate)

一般游戏场景中,装备都会有自己固有的逻辑。比如枪支,有型号,同时又支持在不同的介质平台上使用,这样就使得游戏的装备具有了两个变化的维度。

一个变化的维度为“平台的变化”,另一个变化的维度为“型号的变化”。如果我们要写代码实现这款游戏,难道我们针对每种平台都实现一套独立的装备吗?复

用在哪里?如何应对这种“多维度的变化”?如何利用面向对象技术来使得装备可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度?

2.2、意图(Intent)

将抽象部分与实现部分分离,使它们都可以独立地变化。--《设计模式》Gof

桥接模式不能只是认为是抽象和实现的分离,它其实并不仅限于此。其实两个都是抽象的部分,更确切的理解,应该是将一个事物中多个维度的变化分离。

2.3、结构图(Structure)

2.4、模式的组成

桥接模式的结构包括Abstraction、RefinedAbstraction、Implementor、ConcreteImplementorA和ConcreteImplementorB五个部分,其中:

1)抽象化角色(Abstraction):抽象化给出定义,并保存一个对实现化对象(Implementor)的引用。

2)修正抽象化角色(Refined Abstraction):扩展抽象化角色,改变和修正父类对抽象化的定义。

3)实现化角色(Implementor):这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定与抽象化角色的接口定义相同。

实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。

4)具体实现化角色(Concrete Implementor):这个角色给出实现化角色接口的具体实现。

在桥接模式中,两个类Abstraction和Implementor分别定义了抽象与行为类型的接口,通过调用两接口的子类实现抽象与行为的动态组合。

2.5、桥接模式的具体实现

今天我们就以数据库为例来写该模式的实现。每种数据库都有自己的版本,但是每种数据库在不同的平台上实现又是不一样的。比如,微软的SqlServer数

据库有2000、2005、2008、2012、2014、2016、2017版本,后面还会有更新的版本,并且这些版本都是运行在Windows操作系统下的。如果要提供Lunix

操作系统下的SqlServer怎么办呢?如果又要提供IOS操作系统下的SqlServer数据库该怎么办呢?这个情况就可以使用桥接模式,也就是Brige模式。

下面看看具体的实现:

    class Program
{
/// <summary>
/// 该抽象类就是抽象接口的定义,该类型就相当于是Abstraction类型。
/// </summary>
public abstract class Database
{
//通过组合方式引用平台接口,此处就是桥梁,该类型相当于Implementor类型。
protected PlatformImplementor platformImplementor; //通过构造器注入,初始化平台实现。
protected Database(PlatformImplementor implementor)
{
platformImplementor = implementor;
} //创建数据库,该操作相当于Abstraction类型的Operation方法。
public abstract void Create();
} /// <summary>
/// 该抽象类就是实现接口的定义,该类型就相当于是Implementor类型。
/// </summary>
public abstract class PlatformImplementor
{
//该方法就相当于Implementor类型的OperationImp方法
public abstract void Process();
} /// <summary>
/// SqlServer2000版本的数据库,相当于RefinedAbstraction类型。
/// </summary>
public class SqlServer2000 : Database
{
//构造函数初始化
public SqlServer2000(PlatformImplementor implementor) : base(implementor) { } public override void Create()
{
platformImplementor.Process();
}
} /// <summary>
/// SqlServer2005版本的数据库,相当于RefinedAbstraction类型。
/// </summary>
public class SqlServer2005 : Database
{
//构造函数初始化
public SqlServer2005(PlatformImplementor implementor) : base(implementor) { } public override void Create()
{
platformImplementor.Process();
}
} /// <summary>
/// SqlServer2000版本的数据库针对Unix操作系统的具体实现,相当于ConcreteImplementorA类型。
/// </summary>
public class SqlServer2000UnixImplementor : PlatformImplementor
{
public override void Process()
{
Console.WriteLine("SqlServer2000针对Unix操作系统的具体实现。");
}
} /// <summary>
/// SqlServer2005版本的数据库针对Unix操作系统的具体实现,相当于ConcreteImplementorB类型。
/// </summary>
public sealed class SqlServer2005UnixImplementor : PlatformImplementor
{
public override void Process()
{
Console.WriteLine("SqlServer2005针对Unix操作系统的具体实现。");
}
} static void Main(string[] args)
{
#region 桥接模式
//针对不同平台进行扩展,也就是子类化,这个是独立变化的。
PlatformImplementor SqlServer2000UnixImp = new SqlServer2000UnixImplementor(); //数据库版本也可以进行扩展和升级,也进行独立的变化。
Database SqlServer2000Unix = new SqlServer2000(SqlServer2000UnixImp); //以上就是两个维度的变化。 //现在就可以针对Unix操作系统进行操作了。
SqlServer2000Unix.Create(); Console.Read();
#endregion
}
}

运行结果如下:

三、桥接模式的实现要点

1)Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。

2)所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意组合它们,从而获得不同平台上的不同型号。

3)Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式对

比于多继承方案是更好的解决方法。

4)Bridge模式的应用一般在“两个非常强的变化维度”。有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈,换言之两个变化不会导致纵横

交错的结果,并不一定要使用Bridge模式。

3.1、桥接模式的优点

1)把抽象接口与其实现解耦。

2)抽象和实现可以独立扩展,不会影响到对方。

3)实现细节对客户透明,对使用隐藏了具体的实现细节。

3.2、桥接模式的缺点

1)增加了系统的复杂度

3.3、桥接模式的使用场景

1)一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系。

2)设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的。

3)需要跨越多个平台的图形和窗口系统上。

4)一个类存在两个独立变化的维度,且两个维度都需要进行扩展。

四、.NET中桥接模式的实现

学习中……,如果谁有好的代码分享,可以贴出来。

五、总结

桥接模式是连接客户端代码和具体实现代码的一座桥梁,同时它也隔离了实现代码的改变对客户代码的影响。在意图中所说的抽象和实现,这两个部分其

实都是高度抽象的,前面“抽象”是指定义了针对客户端的接口,客户端其实使用的是Abstract类型或者是RefinedAbstract类型,这两个类型只是接口,具体的

实现委托给了Implementor类型了。Abstract类型子类化的扩展也演变成Implementor子类化的变化。依个人理解,Abstract类型和其子类型在客户端代码和真

正实现的代码之间起到了桥梁的作用,隔离了Implementor实现代码的变化,让客户端更稳定,所以意图才说是讲抽象部分和它的实现部分隔离。

C#设计模式学习笔记:(7)桥接模式的更多相关文章

  1. 设计模式学习笔记——Bridge 桥接模式

    先说一下我以前对桥接模式的理解:当每个类中都使用到了同样的属性或方法时,应该将他们单独抽象出来,变成这些类的属性和方法(避免重复造轮子),当时的感觉是和三层模型中的model有点单相似,也就是让mod ...

  2. 设计模式学习笔记--备忘录(Mamento)模式

    写在模式学习之前 什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方式,这就是软件模式:每个模式描写叙述了一个在我们程序设计中常常发生的问题,以及该问题的解决方式:当我们碰到模 ...

  3. 设计模式学习笔记-Adapter模式

    Adapter模式,就是适配器模式,使两个原本没有关联的类结合一起使用. 平时我们会经常碰到这样的情况,有了两个现成的类,它们之间没有什么联系,但是我们现在既想用其中一个类的方法,同时也想用另外一个类 ...

  4. Java-马士兵设计模式学习笔记-装饰者模式

    Java装饰者模式简介 一.假设有一个Worker接口,它有一个doSomething方法,Plumber和Carpenter都实现了Worker接口,代码及关系如下: 1.Worker.java p ...

  5. 研磨设计模式学习笔记2--外观模式Facade

    需求:客户端需要按照需求,执行一个操作,操作包括一个系统中的3个模块(根据配置选择是否全部执行). 外观模式优点: 客户端无需知道系统内部实现,,只需要写好配置文件,控制那些模块执行,简单易用. 外观 ...

  6. 设计模式学习笔记 1.factory 模式

    Factory 模式 用户不关心工厂的具体类型,只知道这是一个工厂就行. 通过工厂的实现推迟到子类里面去来确定工厂的具体类型. 工厂的具体类型来确定生产的具体产品. 同时用户不关心这是一个什么样子的产 ...

  7. 设计模式学习笔记——Composite 组合模式

    用于描述无限层级的复杂对象,类似于描述资源管理器,抽象出每一个层级的共同特点(文件夹和文件,展开事件) 以前描述一个对象,是将整个对象的全部数据都描述清楚,而组合模式通过在对象中定义自己,描述自己的下 ...

  8. 设计模式学习笔记——Visitor 访问者模式

    1.定义IVisitor接口,确定变化所涉及的方法 2.封装变化类.实现IVisitor接口 3.在实体类的变化方法中传入IVisitor接口,由接口确定使用哪一种变化来实现(封装变化) 4.在使用时 ...

  9. Java-马士兵设计模式学习笔记-责任链模式-FilterChain功能

    一.目标 增加filterchain功能 二.代码 1.Filter.java public interface Filter { public String doFilter(String str) ...

  10. Java-马士兵设计模式学习笔记-责任链模式-处理数据

    一.目标 数据提交前做各种处理 二.代码 1.MsgProcessor.java public class MsgProcessor { private List<Filter> filt ...

随机推荐

  1. Referer防盗链

    一.目录展示 分为AProject和BProject两个项目进行测试 二.修改c:\windows\system32\drivers\etc下的hosts文件 三.aindex.jsp 四.binde ...

  2. 保存网页内容到excel

    from selenium import webdriverfrom time import sleepfrom selenium.common.exceptions import NoSuchEle ...

  3. java.io 包下的类有哪些 + 面试题

    java.io 包下的类有哪些 + 面试题 IO 介绍 IO 是 Input/Output 的缩写,它是基于流模型实现的,比如操作文件时使用输入流和输出流来写入和读取文件等. IO 分类 传统的 IO ...

  4. TypeScript躬行记(6)——高级类型

    本节将对TypeScript中类型的高级特性做详细讲解,包括交叉类型.类型别名.类型保护等. 一.交叉类型 交叉类型(Intersection Type)是将多个类型通过“&”符号合并成一个新 ...

  5. NanUI | NanUI 0.7 正式发布

    2020年2月10日 NanUI 0.7版正式发布. 回顾过去的一年,浑浑噩噩.生活上.工作上太多的压力和变数让我身心疲惫,目睹亲人被病痛的摧残的痛苦,无法释怀的生死别离令我沉沦许久:公司业务的变动, ...

  6. Ceph 存储集群2-配置:心跳选项、OSD选项、存储池、归置组和 CRUSH 选项

    一.心跳选项 完成基本配置后就可以部署.运行 Ceph 了.执行 ceph health 或 ceph -s 命令时,监视器会报告 Ceph 存储集群的当前状态.监视器通过让各 OSD 自己报告.并接 ...

  7. 验证码,java

    这几天打算写一个验证码出来 遇到了几个问题 imageio写入失败:原因我创建文件的时候是先建立一个text文本,然后修改后缀,图片写不进去,还有没有编译 图像扭曲:粘连的问题,目前解决图像扭曲的问题 ...

  8. NLP(二十)利用BERT实现文本二分类

      在我们进行事件抽取的时候,我们需要触发词来确定是否属于某个特定的事件类型,比如我们以政治上的出访类事件为例,这类事件往往会出现"访问"这个词语,但是仅仅通过"访问&q ...

  9. 01背包与完全背包(dp复习)

    01背包和完全背包都是dp入门的经典,我的dp学的十分的水,借此更新博客的机会回顾一下 01背包:给定总容量为maxv的背包,有n件物品,第i件物品的的体积为w[i],价值为v[i],问如何选取才能是 ...

  10. 机器学习(ML)九之GRU、LSTM、深度神经网络、双向循环神经网络

    门控循环单元(GRU) 循环神经网络中的梯度计算方法.当时间步数较大或者时间步较小时,循环神经网络的梯度较容易出现衰减或爆炸.虽然裁剪梯度可以应对梯度爆炸,但无法解决梯度衰减的问题.通常由于这个原因, ...