原文 第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. C语言中的函数指针

    C语言中的函数指针 函数指针的概念:   函数指针是一个指向位于代码段的函数代码的指针. 函数指针的使用: #include<stdio.h> typedef struct (*fun_t ...

  2. effective c++ prefer const,enum, inline to #defines

    学习心得 对于纯常量,最好以const对象或者enums替换#define #define FIRST 3 //not good enum { first=1, second=2 } ; int nu ...

  3. 利用HttpOnly来防御xss攻击

    xss的概念就不用多说了,它的危害是极大的,这就意味着一旦你的站点出现xss漏洞,就能够运行随意的js代码,最可怕的是攻击者利用js获取cookie或者session劫持,假设这里面包括了大量敏感信息 ...

  4. UITabBarController详细说明(简介和设置)

    [objc] view plaincopy - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions ...

  5. $.ajax通路RESTful Web Service一个错误:Unsupported Media Type

    最近项目,使用头版jquery ajax访问背景CXF发布时间rest维修,结果遇到了错误"Unsupported Media Type". 公布的服务java代码例如以下: im ...

  6. 笔试题&amp;面试题:输入一个维度,逆时针打印出一个指定矩阵

    称号:考虑到用户层面.打印出指定的矩阵,例如,一个给定的用户10,例如,下面的输出应被视为在图: 程序如下所示: #include <stdio.h> #include <mallo ...

  7. Android系统APN配置具体解释

     Android 系统APN配置具体解释 这些天一直在调系统原生的Settings.apk里面APN配置的问题.在设置里面手动添加了APN配置选项.可是在界面上还是看不到.所以跟了下代码.原以为就是简 ...

  8. S性能 Sigmoid Function or Logistic Function

    S性能 Sigmoid Function or Logistic Function octave码 x = -10:0.1:10; y = zeros(length(x), 1); for i = 1 ...

  9. 运行safari提示:无法启动此程序,因为计算机中丢失 QTCF.dll

    解决办法: 1.去百度搜索“QTCF.dll”,找到一个靠谱的下载地址获取到该dll文件: 2.将文件放到 安装目录:Safari\Apple Application Support 下边.

  10. ORM武器:NHibernate(三)五个步骤+简单对象CRUD+HQL

    前面的两篇文章中.我们对NHibernate已经做了大致了解 <ORM利器:NHibernate(一)简单介绍>Nhibernate的作用:攻克了对象和数据库的转化问题 <ORM利器 ...