原文 第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. 应对黑客攻击SQL SERVER数据库中的一个案例

    最近发现挂在网上server不知怎的,重新启动,那server现在主要是开始IIS服务,SQL SERVER 服务. 远程登录.发现系统响应十分缓慢.一个明显的停滞感,打开任务管理器,CPU在基本用法 ...

  2. [LeetCode118]Pascal's Triangle

    题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,R ...

  3. Android UI - 实现广告Banner旋转木马效果

    Android UI - 实现广告Banner旋转木马效果 前言 本篇博客要分享的一个效果是实现广告Banner轮播效果,这个效果也比較常见,一些视频类应用就常常有,就拿360影视大全来举例吧: 用红 ...

  4. 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

    文件夹      [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器開始(八)      [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入 ...

  5. HDOJ 4745 Two Rabbits DP

    Two Rabbits Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Tot ...

  6. Gradle 载入中 Android 下一个.so档

    1.在project下新建 jni/libs  目录   . jni 是和原来的libs  同级 ,将全部的.so文件放入 新建的libs文件下 2.在build.gradle 文件里新增下面内容到a ...

  7. OpenGL【2 坐标转换】

    // OpenGL.cpp : 自定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include & ...

  8. 定向爬虫之爬一爬各个学校新闻的认识(【1】对Url的认识)

    昨天早上,我习惯性的打开博客园,看一看别人的写的博客.突然想起,自己好像没有写过什么博客,所以就心血来潮,把我现在做得事情写出来, 这也是对我目前的学习的一种总结.望大神指点.... 对于一间学校的新 ...

  9. ZOJ 2760 How Many Shortest Path(Dijistra + ISAP 最大流)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 题意:给定一个带权有向图 G=(V, E)和源点 s.汇点 t ...

  10. Flex里的特效

      Flex中提供了丰富的效果组件.因为效果是一种依据时间渐变的过程,因此全部效果都具有duration属性,用来设置播放时间(以毫秒为单位).也能够通过设置repeatCount属性和repeatD ...