初学设计模式之桥接模式

初学设计模式之桥接模式

1、什么是桥接模式

官方解答:将抽象部分与实现部分分离,使它们都独立的变化

2、先感性的认识一下桥接模式

一看这么官方的解释,这车速,有点晕车,没关系,开车之前前咱们先骑自行车感受一下慢速行驶。

假如有一道常识题希望答题人输出的正确 答案为:居里夫人是化学家(干扰因素有雨果、生物学家)

选择题:A  居里夫人是化学家

B  居里夫人是生物学家、

C  雨果是化学家

D  雨果是生物学家

连线题:(人名)         是            (头衔)

居里夫人                           化学家

雨果                                  生物学家

如果你是出题人你会选择哪种形式?假如现在又加入了干扰因素贝多芬,另外又加了一个出题的干扰维度国籍:波兰,中国。  很显然,出题人为了方便,会选择连线题的方式,首先连线题重复字数较少,而且,如果增加出题的干扰因素,选择题还需要重新排列选项,工作量很大,连线题只需要再增加一个属性维度或者在属性下面再增加一个内容即可,纵向横向可以随意扩展。桥接模式就相当于连线题,把属性桥接到一串,也就是把抽象类桥接到一起。这样的话抽象类里面继承的具体子类可以随意扩展,再拓展多个其他抽象类也完全可以,实现抽象部分与实现部分分离,方便编写、调试和维护。

3、一起来看一个编程需求

首先读一句熟悉的话:老师粉笔写字

我们把老师看做一个对象,那么它属于职业类,既然它是类那么它就还会有其他对象,比如工程师等;粉笔看成一个对象,那么它属于一个撰写工具类,同样该类也包含钢笔等;如果用面向对象的编程来实现打印这样一句话,要求可能的输出为:老师粉笔写字;老师用钢笔写字;工程师用粉笔写字;工程师用钢笔写字。同时可能在今后的程序维护中每个还会扩展更多对象,该怎么实现程序呢?

4、传统的面向对象编程方法实现

如果用传统的面向对象的编程方法去实现:建立人的基类,然后继承人类生成具体的老师类和工程师类,继承具体的老师类生成老师用粉笔写字类和老师用钢笔写字类,继承具体的工程师类生成工程师用粉笔写字类和工程师用钢笔写字类。在主函数中生成老师用粉笔写字类的对象直访问成员函数,其他对象也同理,下面是具体的实现程序。

  1 /*用普通方法实现 老师用粉笔写字*/
  2 #include<iostream>
  3 using namespace std;
  4
  5 //人作为初始基类
  6 class People
  7 {
  8 public:
  9     void writing()
 10     {
 11         cout << "输出:";
 12     }
 13 };
 14
 15 //继承 人基类 生成 老师类
 16 class Teacher :public People
 17 {
 18 public:
 19     void writing()
 20     {
 21         m_people.writing();
 22         cout << "老师";
 23     }
 24 protected:
 25     People m_people;
 26
 27 };
 28
 29 //继承 老师类 生成 老师用粉笔写字类
 30 class TeacherChalkWriting :public Teacher
 31 {
 32 public:
 33     void writing()
 34     {   m_teacher.writing();
 35         cout << "用粉笔写字"<<endl;
 36     }
 37 protected:
 38     Teacher m_teacher;
 39 };
 40
 41 //继承 老师类 生成 老师用钢笔写字类
 42 class TeacherPenWriting :public Teacher
 43 {
 44 public:
 45     void writing()
 46     {
 47         m_teacher.writing();
 48         cout << "用钢笔写字"<<endl;
 49     }
 50 protected:
 51     Teacher m_teacher;
 52 };
 53
 54 //继承 人基类 生成 工程师类
 55 class Engineer :public People
 56 {
 57 public:
 58     void writing()
 59     {
 60         m_people.writing();
 61         cout << "工程师";
 62     }
 63 protected:
 64     People m_people;
 65
 66 };
 67
 68 //继承 工程师类 生成 工程师用粉笔写字类
 69 class EngineerChalkWriting :public Engineer
 70 {
 71 public:
 72     void writing()
 73     {
 74         m_engineer.writing();
 75         cout << "用粉笔写字" << endl;
 76     }
 77 protected:
 78     Engineer m_engineer;
 79 };
 80
 81 //继承 工程师类 生成 工程师用钢笔写字类
 82 class EngineerPenWriting :public Engineer
 83 {
 84 public:
 85     void writing()
 86     {
 87         m_engineer.writing();
 88         cout << "用钢笔写字" << endl;
 89     }
 90 protected:
 91     Engineer m_engineer;
 92 };
 93
 94 //主函数
 95 int main()
 96 {
 97     TeacherChalkWriting m_teacherChalkWriting;//利用 老师用粉笔写字类 生成对象
 98     m_teacherChalkWriting.writing();          //调用writing函数
 99
100     TeacherPenWriting m_teacherPenWriting;    //利用 老师用钢笔写字类 生成对象
101     m_teacherPenWriting.writing();            //调用writing函数
102
103     EngineerChalkWriting m_engineerChalkWriting;//利用 工程师用粉笔写字类 生成对象
104     m_engineerChalkWriting.writing();          //调用writing函数
105
106     EngineerPenWriting m_engineerPenWriting;    //利用 工程师用钢笔写字类 生成对象
107     m_engineerPenWriting.writing();            //调用writing函数
108
109     getchar();//为了留住输出界面,按任意键结束
110     return 0;
111 }

分析:程序一眼看上去似乎没啥问题,但是仔细思考一下程序是不是有一些不足的地方,比如从代码编写和维护角度去考虑

稍加思考就会发现:

1)代码的重复度过高,不精简

2)如果再扩展一个乃至多个维度:在教室里老师用粉笔写字,大学校园的教室里老师用粉笔写字,中国大学校园的教室里老师用粉笔写字,就像要出选择题一样要重新排列很多内容,需要一个一个 类的去继承,不方便扩展

5、利用桥接模式去实现

既然上述实现过程有弊端,那然我们用用桥接模式设计一下程序,将一个属性的抽象类作为另外一个属性抽象类的成员变量串起来,实现的代码如下:

  1 /*用桥接模式实现 老师用粉笔写字*/
  2 #include<iostream>
  3 using namespace std;
  4
  5 //人作为初始基类
  6 class People
  7 {
  8 public:
  9     void writing()
 10     {
 11         cout << "输出:";
 12     }
 13 };
 14
 15 //撰写工具抽象类,可以衍生出粉笔、钢笔等
 16 class AbstractWritingTool
 17 {
 18 public:
 19     virtual void writing()
 20     {
 21         void;
 22     };
 23 };
 24
 25 //职业抽象类,可以衍生出老师、工程师等
 26 class AbstractProfession:public People
 27 {
 28 public:
 29     virtual void writing()
 30     {
 31         void;
 32     }
 33 public:
 34     People people;
 35     AbstractWritingTool *m_abstractWritingTool;
 36 };
 37
 38 //继承职业抽象类,衍生出老师类
 39 class Teacher :public AbstractProfession
 40 {
 41 public:
 42     void writing()
 43     {
 44         people.writing();
 45         cout << "老师";
 46         m_abstractWritingTool->writing();
 47     };
 48 };
 49
 50 //继承职业抽象类,衍生出工程师类
 51 class Engineer :public AbstractProfession
 52 {
 53 public:
 54     void writing()
 55     {
 56         people.writing();
 57         cout << "工程师";
 58         m_abstractWritingTool->writing();
 59     };
 60
 61 };
 62
 63 //继承撰写工具抽象类,衍生出粉笔写字类
 64 class ChalkWriting :public  AbstractWritingTool
 65 {
 66 public:
 67     void writing()
 68     {
 69         cout << "用粉笔写" << endl;
 70     };
 71 };
 72
 73 //继承撰写工具抽象类,衍生出钢笔写字类
 74 class PenWriting :public  AbstractWritingTool
 75 {
 76 public:
 77     void writing()
 78     {
 79         cout << "用钢笔写" << endl;
 80     };
 81 };
 82
 83 //主函数
 84 int main()
 85 {
 86     ChalkWriting* m_chalkWriting = new ChalkWriting;   //生成粉笔写字对象
 87     PenWriting *m_penWriting = new PenWriting;         //生成钢笔写字对象
 88
 89     Teacher m_teacher;                                 //生成老师对象
 90     m_teacher.m_abstractWritingTool= m_chalkWriting;   //用生成粉笔写字对象给老师的撰写工具进行赋值
 91     m_teacher.writing();                               //调用writing函数
 92     m_teacher.m_abstractWritingTool = m_penWriting;    //用生成钢笔写字对象给老师的撰写工具进行赋值
 93     m_teacher.writing();                               //调用writing函数
 94
 95     Engineer m_engineer;                                 //生成工程师对象
 96     m_engineer.m_abstractWritingTool = m_chalkWriting;  //用生成粉笔写字对象给工程师的撰写工具进行赋值
 97     m_engineer.writing();                               //调用writing函数
 98     m_engineer.m_abstractWritingTool = m_penWriting;    //用生成钢笔写字对象给工程师的撰写工具进行赋值
 99     m_engineer.writing();                               //调用writing函数
100
101     getchar();//保留输出界面,按任意键结束
102     return 0;
103 }

我们可以看到可以得到和上面一样的输出,但是这样做代码的重读量减少了,更重要的是如果再增加地点维度,只要再新建立一个地点抽象类就可以,如果在职业属性下再扩展医生、公务员等,只需要创建子类去继承职业抽象类就可以了,实现了抽象类的随意扩展(横向的),每个抽象类衍生出的子类也可以随意拓展(纵向的),这就是官方解释的抽象部分与实现部分分离,各自可以实现独立变化。

6 、小结

最后用图去对比一下普通方法(图 6.1)与桥接模式(图 6.2)的不同

  图6.1 普通方法

图6.2 桥接模式

邮箱:[email protected]

原文地址:https://www.cnblogs.com/wuhongjian/p/11518074.html

时间: 2024-11-05 08:55:09

初学设计模式之桥接模式的相关文章

设计模式之桥接模式

桥接模式:实现系统可能有多角度分类,每一种分类都有可能的变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合 下面的实例是一个手机软件的实例,对于手机来说,我们可以从手机的品牌进行分类,也可以从软件角度分类(功能机),同时手机品牌与手机软件是一个 聚合的关系. 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threadi

JS设计模式(桥接模式)

<!--引入的核心JS文件--> <script type="text/javascript" src="CommonUtil.js"></script> <script type=text/javascript charset=utf-8> <!--JS设计模式(桥接模式)--> //桥接模式:主要是把抽象和现实分离开来,使他们独立开来 //应用场景:事件监听回掉机制 window.onload=func

如何让孩子爱上设计模式 ——10.桥接模式(Bridge Pattern)

如何让孩子爱上设计模式 --10.桥接模式(Bridge Pattern) 我有故事,你有酒吗?这年头写个技术文不讲个故事都不行,行,我讲: 还有发现很多的技术博文都开始有喜欢往文中插入几个表情的趋势了, 但是你真的插的姿势对了吗?这种事情不是随便插的,来来来,给你 见识下如何在适当的场景插入适当的表情以让读者感觉到易可赛艇, 本文以讲故事插表情为主,讲述桥接模式为辅,多图预警, 简书上排版可能有些问题,最佳排版可见: https://www.zybuluo.com/coder-pig/note

【设计模式】——桥接模式

桥接模式(Bridge),将抽象部分与它的实现部分分离,使他们都可以独立地变化. 什么是抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义.实现指的是抽象类和它的派生类用来实现自己的对象.实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少他们之间的耦合.也就是说在我们发现需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放-封闭原则时,就应该考虑用桥接模式. 桥接模式基本代码 #include <iostrea

设计模式之桥接模式(八)

设计模式之桥接模式 一.引言 每个人都有吃饭睡觉的行为,这时我们可以抽象出来一个人类型,然后让每个人去继承人类型,这时,每增加一个人,我们只需扩展一个子类就可以了,但是,人类型需要增加行为时,比如增加一个玩手机的行为,我们只许在人类型中扩展玩手机这一个方法,但是对于子类来说,如果这时子类数量相当庞大时,子类需要进行大量的修改. 我们可以使用桥接模式,将抽象和实现分离. 二.介绍 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象

图解Java设计模式之桥接模式

图解Java设计模式之桥接模式 手机操作问题 传统方案解决手机操作问题 传统方案解决手机操作问题分析 桥接模式(Bridge)-基本介绍 桥接模式解决手机操作问题 桥接模式在JDBC中的源码解析 桥接模式的注意事项和细节 桥接模式其它应用场景 手机操作问题 现在对不同手机类型的不同品牌实现操作编程(比如 :开机.关机.上网.打电话等等),如图 : 传统方案解决手机操作问题 传统方法对应的类图 传统方案解决手机操作问题分析 1)扩展性问题(类爆炸),如果我们再增加手机的样式(旋转式),就需要增加各

java设计模式之桥接模式

桥接模式 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦.这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类.这两种类型的类可被结构化改变而互不影响.我们通过下面的实例来演示桥接模式(Bridge Pattern)的用法.其中,可以使用相同的抽象类方法但是不同的桥接实现类,来画出不同颜色的圆. 桥接模式所涉及的角色有:抽象化(Abstraction)角色:抽象化给出的

【设计模式】桥接模式

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类.这两种类型的类可被结构化改变而互不影响. 我们通过下面的实例来演示桥接模式(Bridge Pattern)的用法.其中,可以使用相同的抽象类方法但是不同的桥接实现类,来画出不同颜色的圆. 介绍 意图:将抽象部分与实现部分分离,使它们都可以独立的变化. 主要解决:在有多

大话设计模式_桥接模式(Java代码)

合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承. 桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立变化. 解释:即一个系统可以有多种分类实现,把没种分类独立出来,让他们可以独自变化,减少他们之间的耦合. 简单描述:1个Abstraction类,持有一个Implementor的引用,其方法中调用此Implementor引用的对应方法 大话设计模式中的截图: 代码例子: Abstraction类: 1 package com.longsheng.bridge; 2 3 publi