一、目录概要

二、问题探究

需求:假设要设计一个电脑商场管理系统的某个模块设计,电脑分为品牌和类型两个纬度,我们应该怎么解决?

按照初学者的思路,利用继承就能简单粗暴的实现,那我们来看下这种思路的设计类图。

从电脑纬度划分

  1. package com.aaron.bridge;
  2. public interface Computer {
  3. public void sale();
  4. }
  5. class Desktop implements Computer{
  6. @Override
  7. public void sale() {
  8. System.out.println("台式电脑");
  9. }
  10. }
  11. class Laptop implements Computer{
  12. @Override
  13. public void sale() {
  14. System.out.println("笔记本电脑");
  15. }
  16. }
  17. class Pad implements Computer{
  18. @Override
  19. public void sale() {
  20. System.out.println("平板电脑");
  21. }
  22. }

从品牌纬度划分

  1. package com.aaron.bridge;
  2. // 宏碁品牌的三种类型
  3. public class AcerDesktop extends Desktop{
  4. @Override
  5. public void sale() {
  6. System.out.println("宏碁台式机");
  7. }
  8. }
  9. class AcerLaptop extends Laptop{
  10. @Override
  11. public void sale() {
  12. System.out.println("宏碁笔记本电脑");
  13. }
  14. }
  15. class AcerPad extends Pad{
  16. @Override
  17. public void sale() {
  18. System.out.println("宏碁平板电脑");
  19. }
  20. }
  1. package com.aaron.bridge;
  2. // 苹果品牌的三种类型
  3. public class AppleDesktop extends Desktop{
  4. @Override
  5. public void sale() {
  6. System.out.println("苹果台式机");
  7. }
  8. }
  9. class AppleLaptop extends Laptop{
  10. @Override
  11. public void sale() {
  12. System.out.println("苹果笔记本电脑");
  13. }
  14. }
  15. class ApplePad extends Pad{
  16. @Override
  17. public void sale() {
  18. System.out.println("苹果平板电脑");
  19. }
  20. }
  1. package com.aaron.bridge;
  2. //戴尔品牌的三种类型
  3. public class DellDesktop extends Desktop{
  4. @Override
  5. public void sale() {
  6. System.out.println("戴尔台式机");
  7. }
  8. }
  9. class DellLaptop extends Laptop{
  10. @Override
  11. public void sale() {
  12. System.out.println("戴尔笔记本电脑");
  13. }
  14. }
  15. class DellPad extends Pad{
  16. @Override
  17. public void sale() {
  18. System.out.println("戴尔平板电脑");
  19. }
  20. }

问题1:假设我们的系统按照上述思路设计,当我们新增一个品牌的时候,怎么办?

根据上述思路,从品牌纬度扩展品牌时直接新增台式机、笔记本电脑、平板电脑的类即可。

问题2:当我们新增一个机器类型的时候又该怎么办?

根据上述思路,在机器纬度类型扩展。

  1. 添加新的电脑机型。
  2. 在所有的品牌中,都新增新的机型。
  1. package com.aaron.bridge;
  2. // 电脑纬度
  3. public interface Computer {
  4. public void sale();
  5. }
  6. class Desktop implements Computer{
  7. @Override
  8. public void sale() {
  9. System.out.println("台式电脑");
  10. }
  11. }
  12. class Laptop implements Computer{
  13. @Override
  14. public void sale() {
  15. System.out.println("笔记本电脑");
  16. }
  17. }
  18. class Pad implements Computer{
  19. @Override
  20. public void sale() {
  21. System.out.println("平板电脑");
  22. }
  23. }
  24. class MaxPad implements Computer{
  25. @Override
  26. public void sale() {
  27. System.out.println("超大屏电脑");
  28. }
  29. }
  30. // 品牌纬度
  31. public class DellDesktop extends Desktop{
  32. @Override
  33. public void sale() {
  34. System.out.println("戴尔台式机");
  35. }
  36. }
  37. class DellLaptop extends Laptop{
  38. @Override
  39. public void sale() {
  40. System.out.println("戴尔笔记本电脑");
  41. }
  42. }
  43. class DellPad extends Pad{
  44. @Override
  45. public void sale() {
  46. System.out.println("戴尔平板电脑");
  47. }
  48. }
  49. class DellPad extends Pad{
  50. @Override
  51. public void sale() {
  52. System.out.println("戴尔平板电脑");
  53. }
  54. }
  55. class DellMaxPad extends Pad{
  56. @Override
  57. public void sale() {
  58. System.out.println("超大屏平板电脑");
  59. }
  60. }

思考:当我们添加少量的机型和品牌的时候,该方案的代码扩展性还是可以接受的。但是,再往远思考一步。

  1. 假设电脑商城,添加10个品牌,再添加10种机型,怎么办?
  2. 系统已经上线,系统处于维护阶段人力有限,怎么办?

问题:上述问题主要是把电脑和品牌两个纬度耦合。

  1. 违背单一职责原则(一个类只由一个维度影响)
  2. 违背开闭原则(对拓展开放,对修改关闭)。

解决:将机器、品牌两个纬度进行拆分,不要将他们耦合。

三、解决思路

3.1 什么是桥接模式?

将两个维度(抽象、实现)分离,使它们都可以独立地变化。

3.2 桥接模式的分析
  1. 类型:台式机、笔记本电脑、平板电脑。
  2. 品牌:宏碁、苹果、戴尔。

关键:将上述问题拆分成两个纬度类型和品牌。我们刚刚也讨论了,主要解决拓展性问题。当添加一个新的机器类型或者品牌的时候,不会对其他机器类型或者品牌产生影响。

概念:简单谈下概念,重点根据类图和实现代码去理解Abstraction、RefinedAbstraction、Implementor、ConcreteImplementor

Abstraction:抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。

RefinedAbstraction:

扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

Implementor:

定义实现部分的接口,这个接口不用和Abstraction里面的方法一致(根据约定优于配置原则,建议跟Abstraction一致。),通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

ConcreteImplementor:

真正实现Implementor接口的对象。

3.3 桥接模式实现

1、实体部分设计

  1. package com.aaron.bridge;
  2. /**
  3. *
  4. * @author xiaoyongAaron
  5. * 品牌纬度-实现部分接口
  6. */
  7. public interface ImplementorBrand {
  8. public void sale();
  9. }
  10. class ConcreteImplementorAcer implements ImplementorBrand{
  11. @Override
  12. public void sale() {
  13. System.out.println("宏碁品牌");
  14. }
  15. }
  16. class ConcreteImplementorApple implements ImplementorBrand{
  17. @Override
  18. public void sale() {
  19. System.out.println("苹果品牌");
  20. }
  21. }
  22. class ConcreteImplementorDell implements ImplementorBrand{
  23. @Override
  24. public void sale() {
  25. System.out.println("戴尔品牌");
  26. }
  27. }

2、抽象部分设计

  1. package com.aaron.bridge;
  2. /**
  3. * 机器类型纬度-抽象部分
  4. * @author xiaoyongAaron
  5. */
  6. public class AbstractionComputer {
  7. protected ImplementorBrand brand;
  8. public AbstractionComputer(ImplementorBrand brand){
  9. this.brand=brand;
  10. }
  11. public void sale(){
  12. brand.sale();
  13. };
  14. }
  15. /**
  16. * 扩展部分
  17. * @author xiaoyongAaron
  18. */
  19. class RefinedAbstractionDesktop extends AbstractionComputer{
  20. public RefinedAbstractionDesktop(ImplementorBrand brand) {
  21. super(brand);
  22. }
  23. @Override
  24. public void sale() {
  25. //添加自己的特性,实际业务。
  26. paly();
  27. super.sale();
  28. }
  29. public void paly(){
  30. System.out.println("我台式机抗摔打");
  31. }
  32. }
  33. class RefinedAbstractionLaptop extends AbstractionComputer{
  34. public RefinedAbstractionLaptop(ImplementorBrand brand) {
  35. super(brand);
  36. }
  37. @Override
  38. public void sale() {
  39. //添加自己的特性,实际业务。
  40. lighting();
  41. super.sale();
  42. }
  43. public void lighting(){
  44. System.out.println("我笔记本电脑充电5分钟,续航5小时");
  45. }
  46. }
  47. class RefinedAbstractionPad extends AbstractionComputer{
  48. public RefinedAbstractionPad(ImplementorBrand brand) {
  49. super(brand);
  50. }
  51. @Override
  52. public void sale() {
  53. //添加自己的特性,实际业务。
  54. weighting();
  55. super.sale();
  56. }
  57. public void weighting(){
  58. System.out.println("我平板电脑便于携带");
  59. }
  60. }

4、执行结果显示

四、问题回顾

4.1 什么是桥接模式、为什么要桥接?

简单说桥接模式就是把两个纬度分离,所以说当我们在实际开发的时候,遇到两个维度问题的时候,直接条件反射桥接模式。

就像上述问题,当有两个维度(品牌+机器类型)赋予给一个类的时候,基于单一职责原则,需要把它们解耦。那通过上述范例可知,那么我们就需要一座桥一样,把两个纬度用一个中间物(类或者接口)把它们关联起来,从而达到我们的目的。

4.2 桥接模式怎么接?

核心:如何把Implementor对象传递到抽象接口。

  1. 如上述描述,利用构造函数传参。
  2. 创造无参构造函数,添加get、set方法。
  3. 工厂模式:参考设计模式的工厂模式。
  4. IOC控制反转,最经典的就是Spring容器。内部的实现原理原本创建对象都是由我们自己管理,但是把这一步骤交给容器管理,就不用我们担心了。例如在JDBC的设计当中,充当这个角色的就是DriverManage去把对象注入在抽象接口当中。
4.3 桥接模式本质和经验
  1. 本质:抽象与实现(两个纬度)分离。
  2. 多用对象组合(has-A),少用继承。
  3. 开闭原则:我们应该对代码拓展开放,拒绝代码修改。

实际应用场景:

作者:码农皮邱

原文:https://www.cnblogs.com/qiuyong/p/6357839.html

推荐:您的支持是对博主深入思考总结的最大鼓励,要是有需要关注公众号与作者面对面对话交流~

说明:本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,尊重作者的劳动成果。

桥接模式:探索JDBC的接口的更多相关文章

  1. 设计模式:桥接模式及代码示例、桥接模式在jdbc中的体现、注意事项

    0.背景 加入一个手机分为多种款式,不同款式分为不同品牌.这些详细分类下分别进行操作. 如果传统做法,需要将手机,分为不同的子类,再继续分,基本属于一个庞大的多叉树,然后每个叶子节点进行相同名称.但是 ...

  2. Java设计模式之《桥接模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6497919.html 这里摘抄一份他处的概念,你可以不必理会,先看下面得讲解与实例, ...

  3. 设计模式(7)--Bridge(桥接模式)--结构型

    1.模式定义: 桥接模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式.桥接模式的用意是“将抽象化(Abstraction)与实现化(Impleme ...

  4. [Unity 设计模式]桥接模式(BridgePattern)

    1.前言 继上一讲IOC模式的基础上继续本讲桥接模式,笔者感觉桥接模式是23种设计模式中桥接模式是最好用但也是最难理解的设计模式之一,23中设计模式就好武侠剧中一本武功秘籍,我们在工作过程中想要熟练运 ...

  5. 桥接模式:探索JDBC底层实现

    一.目录概要 二.问题探究 需求:假设要设计一个电脑商场管理系统的某个模块设计,电脑分为品牌和类型两个纬度,我们应该怎么解决? 按照初学者的思路,利用继承就能简单粗暴的实现,那我们来看下这种思路的设计 ...

  6. java面试题之----jdbc中使用的设计模式(桥接模式)

    1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...

  7. JDBC和桥接模式

    本文参考 网上对于JDBC与桥接模式的理解各有不同,在这片文章里提出的是我个人对于二者的理解,本文参考的其它博文如下: https://blog.csdn.net/paincupid/article/ ...

  8. 桥接模式/bridge模式/对象结构型

    意图 将抽象部分与它的实现部分分离,使它们都可以独立的变化. 动机 当一个抽象类有多个实现时,通常用继承来协调它们.但是继承机制将抽象和实现固定,难以对抽象部分和实现部分独立地进行修改.扩充和重用. ...

  9. Java设计模式-桥接模式(Bridge)

    桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...

随机推荐

  1. MySQL5.6 新特性之GTID【转】

    转自 MySQL5.6 新特性之GTID - jyzhou - 博客园http://www.cnblogs.com/zhoujinyi/p/4717951.html 背景: MySQL5.6在5.5的 ...

  2. 145.Binary Tree Postorder Traversal---二叉树后序非递归遍历

    题目链接 题目大意:后序遍历二叉树. 法一:普通递归,只是这里需要传入一个list来存储遍历结果.代码如下(耗时1ms): public List<Integer> postorderTr ...

  3. IT行业经典面试技巧及方法思路。

    问题1:为什么从上家公司离职?”能说说原因吗? 首先,作为一个从事招聘的HR,并不认为追问面试者为什么从上一家公司离职是个明智的做法起码不应该在面试一开始就抛出这个问题,一个较为明显的原因是因为这会引 ...

  4. 看懂 MySQL 慢查询日志

    MySQL中的日志包括: 错误日志.二进制日志.通用查询日志.慢查询日志等等. 这里主要介绍下比较常用的两个功能:通用查询日志和慢查询日志. 1)通用查询日志:记录建立的客户端连接和执行的语句. 2) ...

  5. 关于IdByName 为什么一个消息主题要有 Id和 Name的解释

  6. bug-bug-bug

    #-*-coding:utf-8-*- import urllib import urllib2 import re import json import threading import reque ...

  7. 二、python框架相关知识体系

    Django框架 1.django框架.flask框架和Tornado框架的区别? django框架,内置组件多,自身功能强大,是一个大而全的框架,ORM.Admin.中间件.Form.ModelFr ...

  8. 深度学习方法(十一):卷积神经网络结构变化——Google Inception V1-V4,Xception(depthwise convolution)

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.机器学习技术感兴趣的同学加入. 上一篇讲了深度学习方法(十) ...

  9. pymongo的一些操作

    参考:http://www.yiibai.com/mongodb/mongodb_drop_collection.html http://www.cnblogs.com/zhouxuchen/p/55 ...

  10. ASP.NET WebAPI 06 HttpMessageHandler管道

    HttpMessageHandler管道 在Web API的中,微软为了更好的进行架构扩展,采用的了一套管道设计----HttpMessageHander(其实WCF也有类似架构). 在整个管道中的头 ...