Android设计模式源码解析之桥接模式
模式介绍
将抽象部分与实现部分分离,使它们都可以独立的变化。
- 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系。
- 设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的。
- 需要跨越多个平台的图形和窗口系统上。
- 一个类存在两个独立变化的维度,且两个维度都需要进行扩展。
- 抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。 修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
- 实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接 口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
- 具体实现化(ConcreteImplementor)角色:这个角色给出实现化角色接口的具体实现。
其实Java的虚拟机就是一个很好的例子,在不同平台平台上,用不同的虚拟机进行实现,这样只需把Java程序编译成符合虚拟机规范的文件,且只用编译一次,便在不同平台上都能工作。 但是这样说比较抽象,用一个简单的例子来实现bridge模式。
编写一个程序,使用两个绘图的程序的其中一个来绘制矩形或者原型,同时,在实例化矩形的时候,它要知道使用绘图程序1(DP1)还是绘图程序2(DP2)。
(ps:假设dp1和dp2的绘制方式不一样,它们是用不同方式进行绘制,示例代码,不讨论过多细节)
}
//具体的绘图程序类dp2
}
}
}
}
}
//修正抽象化角色Refined Abstraction(矩形)
}
}
}
//修正抽象化角色Refined Abstraction(圆形)
}
}
}
}
//具体实现化逻辑ConcreteImplementor
}
}
}
//实现了接口方法,使用DP2进行绘图
}
}
在这个示例中,图形Shape类有两种类型,圆形和矩形,为了使用不同的绘图程序绘制图形,把实现的部分进行了分离,构成了Drawing类层次结构,包括V1Drawing和V2Drawing。在具体实现类中,V1Drawing控制着DP1程序进行绘图,V2Drawing控制着DP2程序进行绘图,以及保护的方法drawRantangle,drawCircle(Shape类中) 。
在Android中也运用到了Bridge模式,我们使用很多的ListView和BaseAdpater其实就是Bridge模式的运行,很多人会问这个不是Adapter模式,接下来根据源码来分析。
首先ListAdapter.java:
这里先来看一下父类AdapterView。
接着来看ListView的父类AbsListView,继承自AdapterView
}
大家都知道,构建一个listview,adapter中最重要的两个方法,getCount()告知数量,getview()告知具体的view类型,接下来看看AbsListView作为一个视图的集合是如何来根据实现化对象adapter来实现的具体的view呢?
}
接着来看
接下来在ListView中,onMeasure调用了obtainView来确定宽高,在扩展自己的方法来排列这些view。知道了
这些以后,我们来画一个简易的UML图来看下:
对比下GOF的上图,是不是发现很像呢?实际上最开始研究Adapter模式的时候,越看越不对啊,于是整理结构,画了UML发现这更像是一个bridge模式,那时候对设计模式也是模模糊糊的,于是静下来研究。抽象化的角色一个视图的集合AdapterView,它扩展了AbsListView,AbsSpinner,接下来他们分别扩展了ListView,GridView,Spinner,Gallery,用不同方式来展现这些ItemViews,我们继续扩展类似ListView的PulltoRefreshView等等。而实现化角色Adapter扩展了ListAdpater,SpinnerAdapter,接着具体的实现化角色BaseAdapter实现了他们,我们通过继承BaseAdapter又实现了我们各式各样的ItemView。
这里就是Android工程师的牛X之处了,用一个bridge和adapter来解决了一个大的难题。试想一下,视图的排列方式是无穷尽,是人们每个人开发的视图也是无穷尽的。如果你正常开发,你需要多少类来完成呢?而Android把最常用用的展现方式全部都封装了出来,而在实现角色通过Adapter模式来应变无穷无尽的视图需要。抽象化了一个容器使用适配器来给容器里面添加视图,容器的形状(或理解为展现的方式)以及怎么样来绘制容器内的视图,你都可以独自的变化,双双不会干扰,真正的脱耦,就要最开始说的那样:“将抽象部分与实现部分分离,使它们都可以独立的变化。”
从上面的两个案例,我们可以看出,我们在两个解决方案中都用到bridge和adapter模式,那是因为我们必须使用给定的绘图程序(adapter适配器),绘图程序(adapter适配器)有已经存在的接口必须要遵循,因此需要使用Adapter进行适配,然后才能用同样的方式处理他们,他们经常一起使用,并且相似,但是Adapter并不是Bridge的一部分。
实现与使用实现的对象解耦,提供了可扩展性,客户对象无需担心操作的实现问题。 如果你采用了bridge模式,在处理新的实现将会非常容易。你只需定义一个新的具体实现类,并且实现它就好了,不需要修改任何其他的东西。但是如果你出现了一个新的具体情况,需要对实现进行修改时,就得先修改抽象的接口,再对其派生类进行修改,但是这种修改只会存在于局部,并且这种修改将变化的英雄控制在局部,并且降低了出现副作用的风险,而且类之间的关系十分清晰,如何实现一目了然。
Android设计模式源码解析之桥接模式的更多相关文章
- Android设计模式源码解析之外观模式(Facade)
https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/facade/elsd ...
- Android设计模式源码解析之Builder模式
https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/builder/mr. ...
- Android -- AsyncTask源码解析
1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+ ...
- Flink 源码解析 —— Standalone session 模式启动流程
Standalone session 模式启动流程 https://t.zsxq.com/EemAEIi 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0 ...
- Android AsyncTask 源码解析
1. 官方介绍 public abstract class AsyncTask extends Object java.lang.Object ↳ android.os.AsyncTask&l ...
- Android EventBus源码解析 带你深入理解EventBus
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...
- Android -- 从源码解析Handle+Looper+MessageQueue机制
1,今天和大家一起从底层看看Handle的工作机制是什么样的,那么在引入之前我们先来了解Handle是用来干什么的 handler通俗一点讲就是用来在各个线程之间发送数据的处理对象.在任何线程中,只要 ...
- Android LayoutInflater源码解析:你真的能正确使用吗?
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 好久没写博客了,最近忙着换工作,没时间写,工作刚定下来.稍后有时间会写一下换工作经历.接下来进入本篇主题,本来没想写LayoutInflater的 ...
- Android HandlerThread源码解析
在上一章Handler源码解析文章中,我们知道App的主线程通过Handler机制完成了一个线程的消息循环.那么我们自己也可以新建一个线程,在线程里面创建一个Looper,完成消息循环,可以做一些定时 ...
随机推荐
- windows service 安装和卸载指令
添加服务: cd C:\Windows\Microsoft.NET\Framework\v4.0.30319InstallUtil.exe D:\OneKeyWebSiteDeployment\Ser ...
- POJ 1330 Nearest Common Ancestors(求最近的公共祖先)
题意:给出一棵树,再给出两个节点a.b,求离它们最近的公共祖先.方法一: 先用vector存储某节点的子节点,fa数组存储某节点的父节点,最后找出fa[root]=0的根节点root. 之后 ...
- POJ 1740
#include <iostream> #define MAXN 100 using namespace std; int _m[MAXN]; bool mark[MAXN]; int m ...
- hadoop倒排索引
1.前言 学习hadoop的童鞋,倒排索引这个算法还是挺重要的.这是以后展开工作的基础.首先,我们来认识下什么是倒拍索引: 倒排索引简单地就是:根据单词,返回它在哪个文件中出现过,而且频率是多少的结果 ...
- 使用 Storyboard Segue 实作 UIViewController 的切换
http://blog.csdn.net/mazhen1986/article/details/7791430 Storyboard 是在 iOS 5 SDK 中才出现的新名词,它其实就是原本的 Xi ...
- 【mysql的编程专题⑤】自定义函数
用户自定义函数(user-defined function,UDF) 是一种对mysql的扩展途径,其用法与内置函数相同 创建自定义函数 语法 create function function_nam ...
- python 利用pop3接收邮件并保存附件
def SaveAttach():# login the pop3 server ,retrive the new mails ,and download the attachments dstdir ...
- [iOS]iPhone进行真机测试(基础版)
买完688个人开发者账号之后,如何进行真机测试呢??看下面 1.打开https://developer.apple.com 然后,输入我们买过688点那个App ID帐号和密码哦!!一定是要支付过的! ...
- 一些CSS技巧
1.网页LOGO背景居中 html { background: #f5f7f9 url(img/logo.png) no-repeat center center fixed; backgro ...
- QTP公开课视频-持续更新中。。。
以下是视频的下载地址: http://pan.baidu.com/share/link?shareid=1760499709&uk=3711405498