Android设计模式系列-适配器模式
对于android开发者来说起,适配器模式简直太熟悉不过,有很多应用可以说是天天在直接或者间接的用到适配器模式,比如ListView。
ListView用于显示列表数据,但是作为列表数据集合有很多形式,有Array,有Cursor,我们需要对应的适配器作为桥梁,处理相应的数据(并能形成ListView所需要的视图)。
正是因为定义了这些适配器接口和适配器类,才能使我们的数据简单灵活而又正确的显示到了adapterview的实现类上。
适配器模式,Adapter Pattern,勇敢的去适配,大量的资源可以重用。
1.意图
适配器模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。
适配器模式分为类适配器模式和对象适配器模式。
关于类适配器模式,因为java的单继承,如果继承一个类,另外的则只能是接口,需要手动实现相应的方法。
热门词汇:类的适配器模式 对象的适配器模式 缺省适配器模式 源类 目标接口
2.结构图和代码
为了简明直接,我省略了相关的其他适配器 ,只以此两个适配器为例。
ListViews做为client,他所需要的目标接口(target interface)就是ListAdapter,包含getCount(),getItem(),getView()等几个基本的方法,为了兼容List<T>,Cursor等数据类型作为数据源,我们专门定义两个适配器来适配他们:ArrayAdapter和CursorAdapter。这两个适配器,说白了,就是针对目标接口对数据源进行兼容修饰。
这就是适配器模式。
其中BaseAdapter实现了如isEmpty()方法,使子类在继承BaseAdapter后不需要再实现此方法,这就是缺省适配器,这也是缺省适配器的一个最明显的好处。
我们以最简单的若干个方法举例如下,ListAdapter接口如下(,为了简单,我省略了继承自Adapter接口):
- public interface ListAdapter {
- public int getCount();
- Object getItem(int position);
- long getItemId(int position);
- View getView(int position, View convertView, ViewGroup parent);
- boolean isEmpty();
- }
抽象类BaseAdapter,我省略其他代码,只列出两个方法,以作示意:
- public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
- // ... ...
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return getView(position, convertView, parent);
- }
- public boolean isEmpty() {
- return getCount() == 0;
- }
- }
ArrayAdapter对List<T>进行封装成ListAdapter的实现,满足ListView的调用:
- public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
- private List<T> mObjects;
- //我只列出这一个构造函数,大家懂这个意思就行
- public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {
- init(context, textViewResourceId, 0, Arrays.asList(objects));
- }
- private void init(Context context, int resource, int textViewResourceId, List<T> objects) {
- mContext = context;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mResource = mDropDownResource = resource;
- mObjects = objects; //引用对象,也是表达了组合优于继承的意思
- mFieldId = textViewResourceId;
- }
- public int getCount() {
- return mObjects.size();
- }
- public T getItem(int position) {
- return mObjects.get(position);
- }
- public View getView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mResource);
- }
- // ... ...
- }
我们就如此成功的把List<T>作为数据源以ListView想要的目标接口的样子传给了ListView,同理CursorAdapter也是一模一样的道理,就不写具体代码了。
适配器本身倒是不难,但是提供了解决不兼容问题的惯用模式。
关于什么时候使用适配器模式,大概有三种情况:
(1). 你想使用一个已经存在的类,而它的接口不符合你的需求,这个在处理旧系统时比较常见。
(2). 你想创建一个可以复用的类,该类可以和其他不相关的类或不可预见的累协同工作,这就是我们android开发者经常碰到的情况:我们常常自定义一个新的Adapter。
(3). 你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口。
3.效果
1.结构性模式
2.上面论述的主要是对象适配器,关于类适配器除了实现目标端口外,还要实现你要兼容的源类,这样可以少写几行代码,但是从组合优于继承的角度看,它总则没有那么的干净。
3.对同一个适配器(即同一个对象)对同样的源进行双向甚至多向的适配,则能使其适用两个甚至多个客户调用。
Android设计模式系列-适配器模式的更多相关文章
- Android设计模式系列
http://www.cnblogs.com/qianxudetianxia/category/312863.html Android设计模式系列(12)--SDK源码之生成器模式(建造者模式) 摘要 ...
- Android设计模式系列--观察者模式
观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下.本文以AbstractCursor为例子,展开分析.观察者模式,Observer Patter ...
- Android设计模式系列--工厂方法模式
工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式.android中用到了太多的工厂类,其中有用工厂方法模式的,当然也有很多工厂并不是使用工厂方法模式的,只是工具 ...
- Android设计模式系列(2)--SDK源码之观察者模式
观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下.本文以AbstractCursor为例子,展开分析.观察者模式,Observer Patter ...
- Android设计模式系列-单例模式
单例模式,可以说是GOF的23种设计模式中最简单的一个. 这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),很有意思,是一个感觉上很干净的模式, ...
- Android设计模式系列(3)--SDK源码之单例模式
单例模式,可以说是GOF的23种设计模式中最简单的一个.这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),很有意思,是一个感觉上很干净的模式,本 ...
- Android设计模式系列--模板方法模式
模板方法,和单例模式是我认为GOF的23中最简单的两种模式.但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分 ...
- Android设计模式系列-组合模式
Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和ViewGroup类的使用.在android UI设计,几乎所有的widget和布局类都依靠这两个类.组合模式,Compos ...
- Android设计模式系列(1)--SDK源码之组合模式
Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和ViewGroup类的使用.在android UI设计,几乎所有的widget和布局类都依靠这两个类.组合模式,Compos ...
随机推荐
- oracle connect by 和start with
网上找了个例子 测试了一下 貌似明白了create table t2(root_id number,id number,name varchar(5),description varchar(10)) ...
- C++中的namespace用法
关键字namespace定义了一个名字空间,里面的变量和函数,声明在此名字空间外使用须在前面加名字空间名称.例如: #include<iostream.h>namespace my{ in ...
- java网络基本类使用(一)
1.怎么获取ip相关信息 import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumera ...
- CentOS7.1 JDK安装 和 CentOS7.1配置yum源
1.卸载自带OPENJDK #查看自身jdk java -verson #查看自身安装的java rpm -qa | grep java #显示如下 python-javapackages-3.4. ...
- SQL Server R2 2008中的SQL Server Management Studio 阻止保存要求重新创建表的更改问题的设置方法
在2008中会加入阻止保存要求重新创建表的更改这个选项.症状表现为修改表结构的时候会"阻止"你. SQL Server 2008“阻止保存要求重新创建表的更改”的错误的解决方案是本 ...
- oh my zsh命令
打开某个文件夹地址,输入 cdf 命令,会自动进入这个文件夹命令行 open ./ 打开当前命令行所在目录的文件夹
- 通过ngx-lua来统计Nginx上的虚拟主机性能数据
Web server调研分析 Filed under: Web Server — cmpan @ 2012-10-29 20:38:34 摘要 简单可依赖的架构首先需要有一个简单可依赖的前端WebSe ...
- poj 3687 Labeling Balls(拓扑排序)
题目:http://poj.org/problem?id=3687题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小.(先保证1号球最轻 ...
- 弹出框页面中使用jquery.validate验证控件
弹出框页面中使用jquery.validate验证控件有几个问题需要解决: 1,弹出框的提交事件完成后如何关闭弹出框页面? 2,提交不成功如何返回当前页? 3,如果知道验证事件成功? 之前笔者都是JS ...
- Rman实现数据库迁移
Rman实现数据库迁移(从库A迁移到库B)环境:服务器A:Oracle10g+AS3服务器B:Oracle10g+AS4准备工作: 1 在数据库B上建立与库A相同的目录结构(若由于磁盘空间等原因可以用 ...