一、目录概要

二、问题探究

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

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

从电脑纬度划分

package com.aaron.bridge;

public interface Computer {
public void sale();
} class Desktop implements Computer{
@Override
public void sale() {
System.out.println("台式电脑");
}
} class Laptop implements Computer{
@Override
public void sale() {
System.out.println("笔记本电脑");
}
} class Pad implements Computer{
@Override
public void sale() {
System.out.println("平板电脑");
}
}

从品牌纬度划分

package com.aaron.bridge;
// 宏碁品牌的三种类型
public class AcerDesktop extends Desktop{
@Override
public void sale() {
System.out.println("宏碁台式机");
}
} class AcerLaptop extends Laptop{
@Override
public void sale() {
System.out.println("宏碁笔记本电脑");
}
} class AcerPad extends Pad{
@Override
public void sale() {
System.out.println("宏碁平板电脑");
}
}
package com.aaron.bridge;

// 苹果品牌的三种类型
public class AppleDesktop extends Desktop{
@Override
public void sale() {
System.out.println("苹果台式机");
}
} class AppleLaptop extends Laptop{
@Override
public void sale() {
System.out.println("苹果笔记本电脑");
}
} class ApplePad extends Pad{
@Override
public void sale() {
System.out.println("苹果平板电脑");
}
}
package com.aaron.bridge;

//戴尔品牌的三种类型
public class DellDesktop extends Desktop{
@Override
public void sale() {
System.out.println("戴尔台式机");
}
} class DellLaptop extends Laptop{
@Override
public void sale() {
System.out.println("戴尔笔记本电脑");
}
} class DellPad extends Pad{
@Override
public void sale() {
System.out.println("戴尔平板电脑");
}
}

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

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

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

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

  1. 添加新的电脑机型。
  2. 在所有的品牌中,都新增新的机型。
package com.aaron.bridge;

// 电脑纬度
public interface Computer {
public void sale();
} class Desktop implements Computer{
@Override
public void sale() {
System.out.println("台式电脑");
}
} class Laptop implements Computer{
@Override
public void sale() {
System.out.println("笔记本电脑");
}
} class Pad implements Computer{
@Override
public void sale() {
System.out.println("平板电脑");
}
} class MaxPad implements Computer{
@Override
public void sale() {
System.out.println("超大屏电脑");
}
} // 品牌纬度
public class DellDesktop extends Desktop{
@Override
public void sale() {
System.out.println("戴尔台式机");
}
} class DellLaptop extends Laptop{
@Override
public void sale() {
System.out.println("戴尔笔记本电脑");
}
} class DellPad extends Pad{
@Override
public void sale() {
System.out.println("戴尔平板电脑");
}
} class DellPad extends Pad{
@Override
public void sale() {
System.out.println("戴尔平板电脑");
}
} class DellMaxPad extends Pad{
@Override
public void sale() {
System.out.println("超大屏平板电脑");
}
}

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

  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、实体部分设计

package com.aaron.bridge;

/**
*
* @author xiaoyongAaron
* 品牌纬度-实现部分接口
*/
public interface ImplementorBrand {
public void sale();
} class ConcreteImplementorAcer implements ImplementorBrand{ @Override
public void sale() {
System.out.println("宏碁品牌");
}
} class ConcreteImplementorApple implements ImplementorBrand{
@Override
public void sale() {
System.out.println("苹果品牌");
}
} class ConcreteImplementorDell implements ImplementorBrand{
@Override
public void sale() {
System.out.println("戴尔品牌");
}
}

2、抽象部分设计

package com.aaron.bridge;

/**
* 机器类型纬度-抽象部分
* @author xiaoyongAaron
*/
public class AbstractionComputer {
protected ImplementorBrand brand; public AbstractionComputer(ImplementorBrand brand){
this.brand=brand;
} public void sale(){
brand.sale();
}; } /**
* 扩展部分
* @author xiaoyongAaron
*/
class RefinedAbstractionDesktop extends AbstractionComputer{
public RefinedAbstractionDesktop(ImplementorBrand brand) {
super(brand);
} @Override
public void sale() {
//添加自己的特性,实际业务。
paly();
super.sale();
} public void paly(){
System.out.println("我台式机抗摔打");
}
} class RefinedAbstractionLaptop extends AbstractionComputer{
public RefinedAbstractionLaptop(ImplementorBrand brand) {
super(brand);
} @Override
public void sale() {
//添加自己的特性,实际业务。
lighting();
super.sale();
} public void lighting(){
System.out.println("我笔记本电脑充电5分钟,续航5小时");
}
} class RefinedAbstractionPad extends AbstractionComputer{
public RefinedAbstractionPad(ImplementorBrand brand) {
super(brand);
} @Override
public void sale() {
//添加自己的特性,实际业务。
weighting();
super.sale();
} public void weighting(){
System.out.println("我平板电脑便于携带");
}
}

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/11107180.html

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

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

桥接模式:探索JDBC底层实现的更多相关文章

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

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

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

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

  3. 桥接模式:探索JDBC的接口

    目录概要 场景问题 假设要设计一个电脑商场管理系统的某个模块设计,电脑分为品牌和类型两个纬度,我们应该怎么解决?我们初学者最容易想到的办法就是利用继承的方式,那利用继承实现的类图又是什么样子呢?我们看 ...

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

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

  5. JDBC和桥接模式

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

  6. 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)

      桥接模式Bridge   Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来   意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展.  意图解析 依赖倒置原 ...

  7. [19/04/26-星期五] GOF23_结构型模式(桥接模式、组合模式)

    一.桥接模式(bridge) 场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构. —— 台式机(联想台式机.戴尔台式机.神舟台式机) 电脑    ——笔记本(联想笔记本.戴尔笔记本 ...

  8. java设计模式5.组合模式、门面模式、享元模式、桥接模式

    组合模式 在面向对象的语言中,树结构有着巨大的威力,一个基于继承的类型的等级结构便是一个数结构,一个基于合成的对象结构也是一个数结构.组合模式将部分与整体的关系用树结构表示出来,使得客户端把一个个单独 ...

  9. 设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)

    结构型模式: – 分类: • 适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式.享元模式 – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题.   结构 ...

随机推荐

  1. 全栈项目|小书架|微信小程序-项目结构设计分包

    前面的文章 介绍了服务端的基础搭建以及用户模块的设计,接下来就是在服务端和客户端实现具体的业务了. 本篇文章先来介绍微信小程序开发的项目结构设计,也就是项目分包情况. 由于项目是在<极客时间-9 ...

  2. Linux环境下安装SVN

    最近在研究svn的代码如何迁移到GitLab,因此借助本文,重新来回顾温习下svn的安装使用. 一.SVN的安装 svn的安装很简单,在互联网的环境,直接执行以下命令行即可. yum install ...

  3. 基于JMeter的Quick Easy FTP Server性能测试

    FTP性能测试 1.引言 1.1背景说明 本测试选用的是一个小型的FTP服务器软件:Quick Easy FTP Server.Quick Easy FTP Server是一个全中文的FTP服务器软件 ...

  4. 【开发笔记】- Linux命令大全

    系统信息  arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  5. 73.移动端Web界面滚动性能优化 Passive event listeners

    题,滚动时候不仅滚动了希望滚动的部分,整体的页面也跟随者上下滚动,整个页面非常卡顿. 这两个页面都用了touch事件 控制台打印如下警告: [Intervention] Unable to preve ...

  6. 一段让人瑟瑟发抖的ABAP代码

    昨天11月1日是万圣节,Jerry在继续忙着调研SAP Commerce Cloud里的产品主数据管理.晚上回家到SAP国外的社交媒体上一看,好热闹啊.国外的SAP从业者们纷纷以各种各样的方式庆祝万圣 ...

  7. MySql时区修改

    1.查看当前时间 > select curtime(); #或select now()也可以+-----------+| curtime() |+-----------+| 15:18:10 | ...

  8. MySQL DataType--当整数列遇到小数

    初始化数据: ## 创建测试表 CREATE TABLE `tb002` ( `c1` ) NOT NULL AUTO_INCREMENT, `c2` ) DEFAULT NULL, `c3` ) D ...

  9. Tomcat启动超时设置

    Tomcat启动超时设置: 处理方法: 1. 在server中找到当前Tomcat双击. 2.在视图中进行修改.(如下图:)

  10. Java重试机制

    重试作用: 对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法.写操作等(要考虑写是否幂等)都不适合重试. 远程调用超时.网络突然中断可以重试.在微服务治理框架中,通常都有自己的重试与 ...