原文 第7章 桥接模式(Bridge Pattern)

定义:

在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。

意图:

将抽象部分与实现部分分离,使它们都可以独立的变化。

结构图:

举例:KFC中的可乐,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
   abstract class KFCFood
    {
        //可乐
        public abstract void KeLe();
        
    }
    //冰镇可乐
    class IcedKeLe : KFCFood
    {
        public override void KeLe()
        
            //冰镇可乐
        }
    }
    //常温可乐
    class NormalKeLe : KFCFood
    {
        public override void KeLe()
        {
            //常温可乐
        }
    }
    //大杯冰镇可乐
    class LargeIcedKeLe : IcedKeLe
    {
        public override void KeLe()
        {
            //大杯冰镇可乐
        }
    }
    //小杯冰镇可乐
    class SmallIcedKeLe : IcedKeLe
    {
        public override void KeLe()
        {
            //小杯冰镇可乐
        }
    }
 
    //大杯常温可乐
    class LargeNormalKeLe : NormalKeLe
    {
        public override void KeLe()
        {
            //大杯常温可乐
        }
    }
 
    //小杯常温可乐
    class SmallNormalKeLe : NormalKeLe
    {
        public override void KeLe()
        {
            //小杯常温可乐
        }
    }
     
    //client
    class Program
    {
        static void Main(string[] args)
        {
            //小杯冰镇可乐
            SmallIcedKeLe keLe = new SmallIcedKeLe();
            keLe.KeLe();
 
 
        }
    }

在上面的例子中我们要的是小杯的冰镇可乐,这个是两个维度(小杯,冰镇)。好假如我们现在要一小杯美国的冰镇可乐(三个维度,美国,小杯,冰镇),这里我们假设可乐有分国籍的(比如:美国可乐,中国可乐等)。

我们又得写好几个类来继承这个美国版的冰镇可乐,如果我们要中国的冰镇可乐,那又得写一大堆的类,而且里面重复的非常多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    //美国冰镇可乐,后面的大杯冰镇可乐,小杯冰镇可乐也都得继承这个类
    class AmericaIcedKeLe : IcedKeLe
    {
        public override void KeLe()
        {
            //美国冰镇可乐
        }
    }
    //小杯美国冰镇可乐
    class AmericaSmallIcedKeLe : IcedKeLe
    {
        public override void KeLe()
        {
            //小杯美国冰镇可乐
        }
    }

但是我们说这样的设计是脆弱的,仔细分析就可以发现,它还是存在很多问题,首先它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起KeLe类变化的原因却有两个,即可乐的品牌和可乐的规格的变化;其次是重复代码会很多,可乐的规格在不同的品牌上也会有一部分的代码是相同的;再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。上面我们分析的变化只是沿着某一个方向,如果变化沿着可乐的品牌和可乐的规格两个方向变化,我们会看到这个类的结构会迅速的变庞大。

下面我们用桥模式来重新设计:

向我们先增加一个品牌类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    //品牌
    abstract class Brand
    {
   
        public abstract void KeLe();
     
    }
 
    //美国可乐
    class AmericaIcedKeLe : Brand
    {
        public override void KeLe()
        {
            //美国可乐
        }
    }

修改原有的基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 abstract  class KFCFood
    {
        protected Brand brand;
 
        public Brand Brand {
            get {
                return brand;
            }
            set {
                brand = value;
            }
        }
        //可乐
        public abstract void KeLe();
        
    }
     
     
        //冰镇可乐
    class IcedKeLe : KFCFood
    {
        public override void KeLe()
        {
            //冰镇可乐
            brand.KeLe();
          
        }
    }
     
     
        //小杯常温可乐
    class SmallIcedKeLe: IcedKeLe 
    {
        public override void KeLe()
        {
            //小杯冰镇可乐
            brand.KeLe();
        }
    }
     
     
     class Program
    {
        static void Main(string[] args)
        {
            //小杯美国牌冰镇可乐
            KFCFood AmericaKeLe = new SmallIcedKeLe();
            AmericaKeLe.KeLe();
 
        }
    }

下次如果来中国牌可乐。非洲可乐,只需要增加一个类继承Brand这个类就行了,不需要重复的去写子类。是不是感觉方便了很多!

实现要点

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

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

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

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

适用场景

在以下的情况下应当使用桥模式:

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

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

3.一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。

4.虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。

设计模式系列文章入口

第7章 桥接模式(Bridge Pattern)的更多相关文章

  1. 桥接模式(Bridge Pattern)

    1,定义           桥接模式(Bridge Pattern),也称为桥梁模式,其用意是将抽象化与实现化脱耦,使得两者可以独立的变化,它可以使软件系统沿着多个方向进行变化,而又不引入额外的复杂 ...

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

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

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

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

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

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

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

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

  6. Net设计模式实例之桥接模式( Bridge Pattern)

    一.桥接模式简介(Brief Introduction) 桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化. Decouple an abstra ...

  7. 转:设计模式-----桥接模式(Bridge Pattern)

    转自:http://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html 记得看原始链接的评论. 学习设计模式也有一段时间了,今天就把我整理 ...

  8. 七个结构模式之桥接模式(Bridge Pattern)

    问题: 当存在多个独立的变化维度时,如果仍采用多层继承结构,会急剧的增加类的个数,因此可以考虑将各个维度分类,使他们不相互影响. 定义: 将抽象部分与它的实现部分进行分离,抽象部分只保留最为本质的部分 ...

  9. C#设计模式——桥接模式(Bridge Pattern)

    一.概述在软件开发中,我们有时候会遇上一个对象具有多个变化维度.比如对汽车对象来说,可能存在不同的汽车类型,如公共汽车.轿车等,也可能存在不同的发动机,如汽油发动机.柴油发动机等.对这类对象,可应用桥 ...

  10. php桥接模式(bridge pattern)

    有点通了 <?php /* The bridge pattern is used when we want to decouple a class or abstraction from its ...

随机推荐

  1. MFC 将文件拖进对话框获得文件信息

    非常多软件都支持直接将文件拖进去进行处理的功能,详细一点如暴风影音,将视频或者音频文件拖进去就会自己主动開始播放,那么这个功能在MFC上面怎么实现的呢?事实上非常easy,过程例如以下: 第一步:将对 ...

  2. c# winform 引用sqlite.dll 运行报错解决方法

    错误信息 :  未能加载文件或程序集“System.Data.SQLite, Version=1.0.81.0, Culture=neutral, PublicKeyToken=db937bc2d44 ...

  3. 如何更改IE查看源代码菜单使用的HTML编辑器

    一:打开注册表。 二:打开"HKEY_CURRENT_USER/SOFTWARE/MICROSOFT/INTERNET EXPLORER"或"HKEY_LOCAL_MAC ...

  4. asp.net弹出层实例

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.c ...

  5. HDU 5002 Tree

    题意: 一棵树  支持删边加边.路径权值加值.路径权值改值.路径求第二大的数字和其个数 思路: LCT的第二题  题意已经把功能都告诉了  比較裸 要注意的是权值加值和改值两个操作的标记下放问题  要 ...

  6. cocos2d-x lua 学习笔记(1) -- 环境结构

    Cocos2d-x 3.0超过环境的版本号来建立和前Cocos2d-x 2.0 差异较大的版本,从同时Cocos2d-x 3.0项目打包成apkAndroid的应用程序文件,步骤,构建环境有些乏味安德 ...

  7. div显示和隐藏

    它是实现比较简单.style.display控制层隐藏或显示属性. <html> <body> <script> function show(){ document ...

  8. java内存分析总结

    1.自带的jconsole工具. (1)假设是从命令行启动,使 JDK 在 PATH 上,执行 jconsole 就可以. (2)假设从 GUI shell 启动,找到 JDK 安装路径,打开 bin ...

  9. Windows PHone 8 获取硬件信息

    /// <summary> /// 获取系统信息 /// </summary> private string GetDeviceInfo() { StringBuilder s ...

  10. HDU 2112 HDU Today (Dijkstra算法)

    HDU Today Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...