写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。
桥接模式(Bridge)
是一种结构型模式。
目录
一、概述
1.1、主要的角色(如果有点懵的话就先跳过着小部分):
1.2、直观的理解桥接模式要干什么:
1.3、上述手机应用例子的UML图:
二、桥接模式的模板
2.1、对象之间的关系用UML图表示如下:
2.2、Java版的代码如下:
一、概述
1、将抽象部分与它的实现部分分离,使它们都可以独立地变化;2、(实现:是指抽象类以及抽象类的派生类,对于它们的实现类。)这些实现类应该分离;3、和 合成|聚合复用原则 相关;4、实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
1.1、主要的角色(如果有点懵的话就先跳过):
主要的角色分两种,但从代码(或技术)实现的角度看(为了充分使用面向对象语言的3大特性封装、继承、多态,还另外需要抽象类或接口)可能有4个:
- 实现类:实现类的抽象类或接口 +实现类
- 新提取的类:新提取的类的抽象类或接口 +新提取的类的实现类
1.2、直观的理解桥接模式要干什么:
以手机应用软件为例,我们有各种需要,如想和人聊天,那么就用微信;如想购物,那么就用淘宝等。并且对于我们不同的手机,有着不同的操作系统,一样可以使用这些软件来满足我们某方面的需求。
现在假设你是应用程序开发者,你需要在开发出微信和淘宝,并且你还要让它们可以在鸿蒙或者苹果手机上运行:
如果按照以前的思路,那肯定是把微信开发两个版本分别运行在鸿蒙和苹果系统上,同样淘宝也是开发两个,这个例子比较简单,这样做的话只要设计四个对象即可,但万一又有新的需求这样就并不一定好使了。就假设现在要开发10个软件,并且都适配4个系统,那么按照以前的思路,那你需要设计 10*4=40 个对象, 如果再多点呢,那工作量将是难以想象,并且你也清除有很多重复适配工作的。
我们可以这样,把操作系统和应用软件分开看:
- 应用软件都定义一个统一的接口,每个应用软件只针对自己要完成的功能进行实现,如微信对接口具体实现的是聊天,淘宝对接口的具体实现是购物。
- 操作系统也都定义一个统一的运行应用程序的接口,每个操作系统针对接口的具体实现是完成对任何一个应用软件对象的正常运行。
这样再结合多态,就可以实现上面概念里的第一句话,‘将抽象部分与它的实现部分分离,使它们都可以独立地变化’,也就是抽象分离出两部分:操作系统 + 应用软件;
并且它们两可以独立增加或减少。
此时你可能会发现对于手机应用程序来说他有着不同的维度,如功能维度和运行环境维度。像这种一个事物但是对应多个维度,也就是说某个目标对象可以被抽象出多个抽象类,那么就可以尝试使用桥接模式,这样也就符合合成|聚合复用原则。
(想简单了解原则的可以点击下面链接)
设计模式2——原则篇极简版
1.3、上述手机应用例子的UML图:
这样子,把操作系统和应用软件分开,那么就需要建6个类。(对于之前说的‘要开发10个软件,并且都适配3个系统’的话,就不需要40个对象了,而是10+4+2=16个对象。其中有2个是操作系统和应用软件的抽象类)
如何使用?(也就是主程序要怎么调用这些对象)
先填装在使用。
如:可以给鸿蒙系统填装一个应用,然后调用操作系统的运行接口就可以让此应用运行。
(注:本例是以操作系统和应用程序看成一个一个类对象为角度,从而可以让操作系统和应用各自实现各自的统一接口,而现实生活中并非如此)
对应上文的角色分类,在本例种,把应用软件看为解决原本问题的实现类,而操作系统是在此基础上又新提取或抽象出的新提取的类。从代码角度讲:新提取的类是主程序最终调用的类,而实现类是被新提取的类调用,刚好对应我们点击图标后,操作系统接收到我们触摸屏幕的信号,然后再启动应用程序。
(再举例:物品-----对应颜色维度和形状维度)
二、桥接模式的模板
2.1、对象之间的关系用UML图表示如下:
2.2、Java版的代码如下:
实现类(抽象):
abstract class Implementor {public abstract void operation();
}
具体的实现类1:
public class ConcreteImplementor1 extends Implementor{@Overridepublic void operation() {System.out.println("具体实现1的方法执行");}
}
具体的实现类2:
public class ConcreteImplementor2 extends Implementor{@Overridepublic void operation() {System.out.println("具体实现2的方法执行");}
}
抽象分类对象(抽象):
abstract class Abstraction {protected Implementor implementor;public void setImplementor(Implementor implementor) {this.implementor = implementor;}public abstract void operation();
}
提炼后的抽象分类对象A:
public class RefinedAbstractionA extends Abstraction {@Overridepublic void operation() {System.out.println("提炼后的A");implementor.operation();}
}
提炼后的抽象分类对象B:
public class RefinedAbstractionB extends Abstraction {@Overridepublic void operation() {System.out.println("提炼后的B");implementor.operation();}
}
主程序(发起请求的类):
public class Main {public static void main(String[] args) {Abstraction abstraction;abstraction = new RefinedAbstractionA();abstraction.setImplementor(new ConcreteImplementor1());abstraction.operation();abstraction.setImplementor(new ConcreteImplementor2());abstraction.operation();System.out.println("------------------");abstraction = new RefinedAbstractionB();abstraction.setImplementor(new ConcreteImplementor1());abstraction.operation();abstraction.setImplementor(new ConcreteImplementor2());abstraction.operation();}
}
这里暂时就不再例其它编程语言的例子了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。
如果觉得本文还不错,就请点个赞给作者一点鼓励吧!如果有建议,也请评论指教和讨论!