您的位置:首页 > 移动开发 > Android开发

android设计模式的使用之适配器模式

2016-04-21 22:25 429 查看
一.适配器模式

适配器模式的描述:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

那么一个适配的过程包括了以下的这四个部分:

使用者Client。

目标接口Target

被适配者Adaptee

适配器Adapter

适用场景:

1.    目前的接口Target不符合我们的需求。比如我们还需要Adaptee中的一些功能。

2.    复用代码。目标接口Target和被适配者Adaptee都是不能轻易修改的。

3.    如果使用者Client想要实现以上两点,那么Client就得实现Target和继承Adaptee,或者实现Target和委托Adaptee来实现。但

       是,这样Client就耦合了Target和Adaptee,不方便维护和复用。那么,本该Client来实现的这些就由适配器Adapter来完成

       了,Client只要调用适配器Adapter就可以了。而Adapter是目标接口Target的实现,经过向上转型:Target mTarget = new

       Adapter(),正好对应了描述”将一个类的接口转换成客户希望的另外一个接口”,而Target和Adaptee是两个互不相干的类(接

       口),但是在Adapter中却能在一起工作。

 
适配器模式的实现方式:

类适配器

对象适配器

区别:类适配器使用多继承方式(extends,implements)来实现,而对象适配器使用委托的方式来实现(委托Adaptee进行连接)。由于类适配器使用了继承方式,所以适用范围不大,如果被适配者Adaptee改变的情况下,我们就需要重新定义适配器Adapter了。而对象适配器则不同,我们可以传入不同的被适配者Adaptee而不用重写Adapter,适用性大大的提高了。

例子:

使用者Client-------------------电视TV(4脚插头)

目标接口Target---------------插头

被适配者Adaptee------------插座(只有2孔,3孔)

适配器Adapter---------------多孔适配器

类适配器的实现需要支持多继承。在java中,多继承一般用extends和implements来共同完成。代码如下:

/**
* TV表示电视类,如果这时来一个电脑类,我就不用重写代码了,直接调用适配器Adapter,告诉它我几孔插头就可以了。
*/
public class TV {
public static void main(String []args){
int type = 4;
System.out.println("这是" + type + "孔插头,正在尝试通电...");
//Connect mConnect = new Adapter(new Adaptee());
Connect mConnect = new Adapter();
mConnect.connect(type);
}
}
/*
* 目标接口:(表示这是一个插头)
* */
interface Connect{
public void connect(int type);
}
/*
* 被适配着,也叫源角色。(表示这是一个插座,只能使用2孔和3孔)
* */
class Adaptee{
//这个插座可以使用两孔插头
public void twoHoldsocket(){
System.out.println("这是一个两孔插座");
}
//这个插座可以使用三孔插头
public void threeHoldsocket(){
System.out.println("这是一个三孔插座");
}
}

/*
*类适配器,用extends和implements来实现多继承。(表示这是一个适配器,可以适配各种多孔)
* */
class Adapter extends Adaptee implements Connect{

@Override
public void connect(int type) {
switch (type){
//当插头是两孔时,符合插座的使用标准
case 2:
this.twoHoldsocket();
System.out.println("找到" + type + "孔插座,可以匹配,通电成功");
break;
//当插头是三孔时,符合插座的使用标准
case 3:
this.threeHoldsocket();
System.out.println("找到" + type + "孔插座,可以匹配,通电成功");
break;
/*当插头是其他孔时,此插座将不能用,需要使用适配器。蛤?那适配器在哪?
*本类就是一个适配器,只要调用我这个connect()方法,我想让它支持几孔都可以。
* 没见我default代码的执行吗,来100孔插头,我都能把它转换成三孔的标准连接通电,屌吧。
*/
default:
this.threeHoldsocket();
System.out.println("没有找到" + type + "孔插座,必须通过适配器通电成功");
break;
}

}
}


对象适配器

对象适配器跟类适配器的差别在于适配器Adapter的实现上稍有不同,它的Adaptee不是靠继承来获取的,而且通过构造方法传入的。如下:

/**
* TV表示电视类,如果这时来一个电脑类,我就不用重写代码了,直接调用适配器Adapter,告诉它我几孔插头就可以了。
*/
public class TV {
public static void main(String []args){
int type = 4;
System.out.println("这是" + type + "孔插头,正在尝试通电...");
//Connect mConnect = new Adapter(new Adaptee());
Connect mConnect = new Adapter(new Adaptee());
mConnect.connect(type);
}
}
/*
* 目标接口:(表示这是一个插头)
* */
interface Connect{
public void connect(int type);
}
/*
* 被适配着,也叫源角色。(表示这是一个插座,只能使用2孔和3孔)
* */
class Adaptee{
//这个插座可以使用两孔插头
public void twoHoldsocket(){
System.out.println("这是一个两孔插座");
}
//这个插座可以使用三孔插头
public void threeHoldsocket(){
System.out.println("这是一个三孔插座");
}
}

/*
*类适配器,用extends和implements来实现多继承。(表示这是一个适配器,可以适配各种多孔)
* */
class Adapter implements Connect{
private Adaptee mAdaptee;
public Adapter(Adaptee mAdaptee){
this.mAdaptee = mAdaptee;
}
@Override
public void connect(int type) {
switch (type){
//当插头是两孔时,符合插座的使用标准
case 2:
mAdaptee.twoHoldsocket();
System.out.println("找到" + type + "孔插座,可以匹配,通电成功");
break;
//当插头是三孔时,符合插座的使用标准
case 3:
mAdaptee.threeHoldsocket();
System.out.println("找到" + type + "孔插座,可以匹配,通电成功");
break;
/*当插头是其他孔时,此插座将不能用,需要使用适配器。蛤?那适配器在哪?
*本类就是一个适配器,只要调用我这个connect()方法,我想让它支持几孔都可以。
* 没见我default代码的执行吗,来100孔插头,我都能把它转换成三孔的标准连接通电,屌吧。
*/
default:
mAdaptee.threeHoldsocket();
System.out.println("没有找到" + type + "孔插座,必须通过适配器通电成功");
break;
}

}
}

二.适配器模式在android中的使用

了解了适配器模式后,我们可以来看看android的源码中最常见的适配器例子:listview的适配器Adapter。按照上面的适配器组成,我们也来划分一下:

使用者Client--------------ListView

目标接口Target----------继承于Adapter的ListAdapter

被适配者Adaptee-------数据源,List<T>

适配器Adaper------------继承于BaseAdapter的各种子类ArrayAdapter,CursorAdapter等

Listview适配数据的使用如下:

<span style="font-size:14px;">String data[] = {"1","2","3","4","5","6","7","8","9","0"};
ListView mListView = (ListView)findViewById(R.id.listview);
ArrayAdapter mArrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,new ArrayList(Arrays.asList(data)));
mListView.setAdapter(mArrayAdapter);
</span>


这里使用了ArrayAdapter这个适配器来说明。android.R.layout.simple_list_item_1是android自带的TextView布局,new ArrayList(Arrays.asList(data))为被适配者Adaptee,也就是数据源。

mListView.setAdapter(mArrayAdapter)真正适配的过程。在使用者Client的角度上是跟我们的例子是很相像的:

Connect mConnect = new Adapter(new Adaptee());
mConnect.connect(4);
</span>


主要区别在于为了适配各种类型的数据,android定义了很多listview的适配器,而且在适配的过程中处理的业务非常多。具体的在复习到listview的适配器的时候再写。盗张图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: