适配器模式与Android中的Adapter

来源:互联网 发布:安卓乳摇软件 编辑:程序博客网 时间:2024/05/22 18:55

一、适配器模式
首先我们简单介绍一下适配器模式,作为设计模式中的常见模式,顾名思义,“适配器”就是起一个适配作用,将两个不兼容的东西“适配”起来。举个例子,你的电脑需要5V的电压输入,但我们插座提供的都是220V电压的电源,那这个时候怎么办呢?买电脑都会附赠一个硕大的黑色矩形设备连接着插座和电脑供电插头,学名电源适配器,它的作用是什么呢?就是把我们插座提供的220V电压转换成电脑需要的5V电压,这就是适配器的作用啦!把一个类的接口转换成我们需要的(或者说,客户代码所需要的)另外一种接口,从而使不匹配的两个类能够一起工作。

二、适配器模式的分类
适配器模式主要分为两种类型,类适配器模式和对象适配器模式。那他们的区别主要有什么区别呢?首先我们要知道,适配的结果都是实现目标接口,这个是必须的,我们称为目标接口,而我们的输入端称为要进行适配的输入类,那么Adapter就是我们的适配器类。既然要实现目标接口,适配器类必然要继承自目标接口,这个是必须的。那你怎么使用输入类提供的方法呢?这就是Java中的两种进行代码重用的方式,继承和复合(composition),对应的就是类适配器模式和对象适配器模式。类适配器模式中,适配器继承自输入类,而对象适配器模式中,适配器拥有一个输入类的实例,实际上是包装了输入类,这样适配器不会继承一些我们不希望用户使用的接口,使用的成本更低而可维护性更高一些。(有关继承和复合的区别和优劣,见《Effective Java》第16条)
实例代码:
1、类适配器模式
输入类:

class Adaptee {    public void get220V() {        System.out.println("输入220V电压");    }}

目标接口:

interface Target {    public void get5V();}

适配器类:

class Adapter extends Adaptee implements Target{    public void get5V() {        get220V();        //经过转换过程        System.out.println("输出5V电压");    }}

这样你的Adapter就可以提供5V的接口,供客户代码使用了。
2、对象适配器模式
首先,目标接口和输入类都没有区别:
输入类:

class Adaptee {    public void get220V() {        System.out.println("输入220V电压");    }}

目标接口:

interface Target {    public void get5V();}

适配器类:

class Adapter implements Target{    // 直接关联被适配类    private Adaptee adaptee;    // 通过构造函数传入具体需要适配的输入类对象    public Adapter (Adaptee adaptee) {        this.adaptee = adaptee;    }    public void get5V() {        this.adaptee.get220V();        //经过转换过程        System.out.println("输出5V电压");    }}

三、Android中的适配器模式
我前面写过RecyclerView的源码的简单解析,里面特别说到了Adapter这个在Android列表中非常重要的组件,而这里就用到了Adapter模式,也就是适配器模式。但你们可能在使用中并不能感觉出来,特别是和这个传统的适配器模式中的两种类型感觉并没有什么相似程度。但实际上我们看一看就可以发现这个Adapter是实际上就是一个Adapter模式的非常好的实践。
我们来从代码中看一看:

package com.example.lee.recyclerviewtest;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import java.util.List;import java.util.zip.Inflater;/** * Created by Lee on 2016/9/28. */public class MainListAdapter extends RecyclerView.Adapter<MainListAdapter.MainListViewHolder>{    private List<String> mStringList;    private LayoutInflater mLayoutInflater;    public MainListAdapter(Context context, List<String> strings){        mLayoutInflater = LayoutInflater.from(context);        mStringList = strings;    }    @Override    public MainListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View itemView = mLayoutInflater.inflate(R.layout.item_layout_main_list, parent, false);        return new MainListViewHolder(itemView);    }    @Override    public void onBindViewHolder(MainListViewHolder holder, int position) {        holder.mainTextView.setText(mStringList.get(position));    }    @Override    public int getItemCount() {        return mStringList.size();    }    public class MainListViewHolder extends RecyclerView.ViewHolder{        public TextView mainTextView;        public MainListViewHolder(View itemView){            super(itemView);            mainTextView = (TextView) itemView.findViewById(R.id.id_main_text_view);        }    }}

为什么说这个是适配器模式?适配器模式的定义是什么?是把不标准的接口统一成一种客户端期望的接口,但实际上现实代码中不光是接口不标准,数据是最不标准的。为什么这么说,RecyclerView的根本作用是用来显示数据的,但显示的数据是程序员自己去确定的,现实的数据类型、数量根本无法统一,那怎么解决数据的显示呢?我们就用Adapter来把千变万化的数据统一成几个标准的接口,而RecyclerView只需要使用这几个标准的接口来得到它所期望的标准对象,比如ViewHolder(实际上就是最终显示的View对象),然后统一显示即可。而Adapter就实现了这几个标准接口,但数据却是千变万化的。
Adapter的构造函数中:

//string参数就是数据项public MainListAdapter(Context context, List<String> strings){        mLayoutInflater = LayoutInflater.from(context);        mStringList = strings;    }

其中的数据完全是我们自己去设定的,这就体现了适配器模式中“不匹配的”输入。

我们从两个接口作为例子来理解一下这个标准接口(目标接口)的存在,你也能更好理解适配器模式的关键
1、在函数getItemCount中:

//用于获取项数目的标准接口@Overridepublic int getItemCount() {    return mStringList.size();}

返回的项数目也是程序使用者自己进行设定的,但目标接口没有变化,就是getItemCount接口,RecyclerView只会知道我需要用此接口来获取项数目,并不需要知道具体返回的值是如何进行获取和转换的。
2、在函数onCreateViewHolder中

@Overridepublic MainListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    View itemView = mLayoutInflater.inflate(R.layout.item_layout_main_list, parent, false);    return new MainListViewHolder(itemView);}

onCreateViewHolder就是RecyclerView在第一次创建itemView时使用的标准接口,RecyclerView并不用知道你是如何去进行生成的,只需要知道此接口返回的是它需要的标准的ViewHolder即可,而如何构建ViewHolder和其主要的itemView完全不是RecyclerView所关注的,就像你的笔记本电脑也不会关注它的电源接口的5V电压是如何转换而来的,它只需要标准的5V电压就可以了。同样,RecyclerView也不会关注你是如何构建ViewHolder的,你可以从千变万化的数据和layout中构建出标准的ViewHolder,这就是Adapter适配器模式的关键所在。

注:如果对于RecyclerView中的调用过程或者使用有不懂的,欢迎看我的另一篇博客《Android中RecyclerView的使用与解析》,链接为http://blog.csdn.net/ll530304349/article/details/52671486
在其中,我着重分析了RecyclerView接口的调用过程,包括复用ViewHolder等,如果理解了那里面的基本流程,相信大家肯定很快就能理解为什么这个Adapter是适配器模式了!

如果觉得我的文章里有任何错误,欢迎评论指正!如果觉得写得好也欢迎大家留言或者点赞,一起进步、一起学习!

1 0
原创粉丝点击