一、引言

今天我们要讲【结构型】设计模式的第二个模式,该模式是【桥接模式】,也有叫【桥模式】的,英文名称:Bridge Pattern。大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称猜肯定是连接什么东西的。因为桥在我们现实生活中经常是连接着A地和B地,再往后来发展,桥引申为一种纽带,比如:丝绸之路是连接亚洲和欧洲的桥梁。有了桥,我们出行方便了,从一个地方到另一个地方在有桥的情况更方便了(此处不许抬杠,当然是需要桥的情况)。桥是针对桥的使用环境来说的,解决了跨越和衔接的问题。在设计模式中的【桥模式】也有类似的概念,是连接了两个不同维度的东西,而且这两个维度又有强烈的变化,什么叫强烈呢,经常变化,什么是经常呢?哈哈,自己理解吧。

二、桥接模式的详细介绍

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版本、2006版本、2008版本,后面还会有更新的版本。并且这些版本都是运行在Windows操作系统下的,如果要提供Lunix操作系统下的SqlServer怎么办呢?如果又要提供IOS操作系统下的SqlServer数据库该怎么办呢?这个情况就可以使用桥接模式,也就是Brige模式。我们就来看看具体的实现吧!

 namespace 桥接模式的实现
{
/// <summary>
/// 该抽象类就是抽象接口的定义,该类型就相当于是Abstraction类型
/// </summary>
public abstract class Database
{
//通过组合方式引用平台接口,此处就是桥梁,该类型相当于Implementor类型
protected PlatformImplementor _implementor; //通过构造器注入,初始化平台实现
protected Database(PlatformImplementor implementor)
{
this._implementor = implementor;
} //创建数据库--该操作相当于Abstraction类型的Operation方法
public abstract void Create();
} /// <summary>
/// 该抽象类就是实现接口的定义,该类型就相当于是Implementor类型
/// </summary>
public abstract class PlatformImplementor
{
//该方法就相当于Implementor类型的OperationImpl方法
public abstract void Process();
} /// <summary>
/// SqlServer2000版本的数据库,相当于RefinedAbstraction类型
/// </summary>
public class SqlServer2000 : Database
{
//构造函数初始化
public SqlServer2000(PlatformImplementor implementor) : base(implementor) { } public override void Create()
{
this._implementor.Process();
}
} /// <summary>
/// SqlServer2005版本的数据库,相当于RefinedAbstraction类型
/// </summary>
public class SqlServer2005 : Database
{
//构造函数初始化
public SqlServer2005(PlatformImplementor implementor) : base(implementor) { } public override void Create()
{
this._implementor.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的具体实现");
}
} public class Program
{
static void Main()
{
PlatformImplementor SqlServer2000UnixImp = new SqlServer2000UnixImplementor();
//还可以针对不同平台进行扩展,也就是子类化,这个是独立变化的 Database SqlServer2000Unix = new SqlServer2000(SqlServer2000UnixImp);
//数据库版本也可以进行扩展和升级,也进行独立的变化。 //以上就是两个维度的变化。 //就可以针对Unix执行操作了
SqlServer2000Unix.Create();
}
}
}

代码都很简单,也有详细的备注,就不多说了。

三、桥接模式的实现要点:
    
    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#设计模式之八桥接模式(Bridge)【结构型】的更多相关文章

  1. Java设计模式13:常用设计模式之桥接模式(结构型模式)

    1. Java之桥接模式(Bridge Pattern) (1)概述: 首先我们说一个生活中的例子:       就拿汽车在路上行驶的来说.即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也 ...

  2. 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)

      桥接模式Bridge   Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来   意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展.  意图解析 依赖倒置原 ...

  3. 设计模式07: Bridge 桥接模式(结构型模式)

    Bridge 桥接模式(结构型模式) 抽象与实现 抽象不应该依赖于实现细节,实现细节应该依赖于抽象. 抽象B稳定,实现细节b变化 问题在于如果抽象B由于固有的原因,本身并不稳定,也有可能变化,怎么办? ...

  4. 设计模式 笔记 桥接模式 Bridge

    //---------------------------15/04/15---------------------------- //Bridge 桥接模式----对象结构型模式 /* 1:意图:将 ...

  5. 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern)

    原文:乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) 作者:webabcd 介绍 ...

  6. 【设计模式】桥接模式 Bridge Pattern

    开篇还是引用吕振宇老师的那篇经典的文章<设计模式随笔-蜡笔与毛笔的故事>.这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了. 现在市面上卖的蜡笔很多,各种型号, ...

  7. python 设计模式之桥接模式 Bridge Pattern

    #写在前面 前面写了那么设计模式了,有没有觉得有些模式之间很类似,甚至感觉作用重叠了,模式并不是完全隔离和独立的,有的模式内部其实用到了其他模式的技术,但是又有自己的创新点,如果一味地认为每个模式都是 ...

  8. 二十四种设计模式:桥接模式(Bridge Pattern)

    桥接模式(Bridge Pattern) 介绍将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,现在使这些操作的抽象 ...

  9. 结构型设计模式之桥接模式(Bridge)

    结构 意图 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 适用性 你不希望在抽象和它的实现部分之间有一个固定的绑定关系.例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换. ...

随机推荐

  1. 201521123114 《Java程序设计》第7周学习总结

    1. 本章学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 Q1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 public b ...

  2. 201521123007《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...

  3. 201521123044 《Java程序设计》第10周学习总结

    1. 本章学习总结 2. 书面作业 本次PTA作业题集异常丶多线程 1.finally题目4-2 1.1 截图你的提交结果 1.2 4-2中finally中捕获异常需要注意什么? 1.无论try-ca ...

  4. JavaSE(十)之Collection总结

    前面几篇把集合中的知识大概都详细的说了一遍,但是我觉得还是要总结一下,这样的话,可以更好的理解集合. 一.Collection接口 首先我们要一张图来说明: Collection接口,它是集合的顶层接 ...

  5. lintcode.245 子树

    子树   描述 笔记 数据 评测 有两个不同大小的二进制树: T1 有上百万的节点: T2 有好几百的节点.请设计一种算法,判定 T2 是否为 T1的子树. 注意事项 若 T1 中存在从节点 n 开始 ...

  6. MinHook测试与分析(x86下 E8,E9,EB,CALL指令测试,且逆推测试微软热补丁)

    依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook的本质就是拦截,就算到现在也是如此认为. 本篇文章是在x86下测 ...

  7. C# 各种常用集合类型的线程安全版本

    在C#里面我们常用各种集合,数组,List,Dictionary,Stack等,然而这些集合都是非线程安全的,当多线程同时读写这些集合的时候,有可能造成里面的数据混乱,为此微软从Net4.0开始专门提 ...

  8. String类的一些常见的获取方法(5)

     String s = "aasfasfdtgsrast"; 1: int a = s.length() //返回字符串的长度 2: char s1 = charAt(int in ...

  9. 【京东账户】——Mysql/PHP/Ajax爬坑之产品列表显示

    一.引言 实现京东的账户项目,功能模块之一,产品列表显示.要用到的是Apach环境,Mysql.PHP以及Ajax. 二.依据功能创建库.表.记录 创建库:jd 创建表:产品表 添加多条记录 /**产 ...

  10. css控制div强制换行

    div{white-space:nowrap;} 自动换行 div{ word-wrap: break-word; word-break: normal; } 强制英文单词断行 div{word-br ...