java设计模式结构篇------适配器模式

核心思想

通过接口之间的协调转换,使原本因接口不兼容的类能协调工作。理解起来很简单,适配器可以同时获得两个接口类的相关特性或是方法,并将其进行配合使用,使其共同完成功能。

简单实现

我们以简单的电源接口为例,手机等小型电子产品充电是需要变压的,充电器的充电插头就是一个适配器,通过它将原先的220v转变为手机需要的5v(我手机是5v的,只是举个栗子)。当然划分一下角色容易理解,我们可以将其分为目标对象,源对象,适配器。

目标对象

在这个例子里很简单,就是手机等小家电。

1
2
3
4
5
6
7
8
9
public class MobilePhone{
public void charging(int voltage) {
if(voltage==5){//我的手机要求5v,不是5v会产生问题。
System.out.println("充电正常");
}else{
System.out.println("充电异常");
}
}
}

源对象

这里就是我们墙上的220v电源了。

1
2
3
4
5
6
7
8
9
public interface Power{//这是电源负责供给电压
public void getVoltage();//只有在这个函数里才能获得电压
}

public class Socket implements Power{
public void getVoltage(){
System.out.println("220v");//插座只有220v
}
}

适配器

就是充电器,充电器就是这里的适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Adapter extends MobilePhone implements Power{
public void getVoltage(){
System.out.println("220v");//插座只有220v
int voltage = getFive(220);//这里是指适配器中还可以有其他的一些逻辑操作
super.charging(voltage);
}

public int getFive(int v){
if(v==220){
return 5;
}else{
return 0;//电压不匹配就断电,安全第一
}
}
}

很简单的实现就可以描述手机的充电过程了。

简单的扩展

要是时常出国了怎么办?是不是需要一个万能充电器,对,你需要的。

多个接口

先看看其他国家的电压多少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface Power{//这是电源负责供给电压
public int getVoltage();//只有在这个函数里才能获得电压
}

public class Socket1 implements Power{
public int getVoltage(){
return 380;//有的国家380v
}
}

public class Socket2 implements Power{
public int getVoltage(){
return 110;//有的国家110v
}
}

public class Socket3 implements Power{
public int getVoltage(){
return 240;//有的国家240v
}
}

多口适配

通过相关类的关联,将多个接口协调到一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Adapter extends MobilePhone {
private Socket1 s1;
private Socket2 s2;
private Socket3 s3;
public void setSocket1(Socket1 s1){
this.s1=s1;
int voltage = getFive(s1.getVoltage());
super.charging(voltage);//充上电了
}

public void setSocket2(Socket2 s2){
this.s2=s2;
int voltage = getFive(s2.getVoltage());
super.charging(voltage);//充上电了
}

public void setSocket3(Socket3 s3){
this.s3=s3;
int voltage = getFive(s3.getVoltage());
super.charging(voltage);//充上电了
}

public int getFive(int v){
if(v==220||v==240||v==380){
return 5;
}else{
return 0;//电压不匹配就断电,安全第一
}
}
}

特点

首先,使用适配器可以增加代码的灵活性,我们可以在适配器中增删查改,而不必去考虑源对象与目标对象,即使删了适配器对目标与源也是没有影响的。除此之外,原有的源和目标对象还是保持独立的,想怎么用都行。

RecyclerView.Adapter

学过Android的小伙伴都应该了解这个内部类,这就是一个典型的适配器模式。我们通过继承实现了这个抽象类,仅通过实现两个抽象方法onCreateViewHolder与onBindViewHolder就可以实现对数据与布局的适配。

onCreateViewHolder(布局绑定)

1
2
3
4
5
6
7
8
9
10
/* @param parent The ViewGroup into which the new View will be added after it is bound to
* an adapter position.
* @param viewType The view type of the new View.
*
* @return A new ViewHolder that holds a View of the given view type.
* @see #getItemViewType(int)
* @see #onBindViewHolder(ViewHolder, int)
*/
@NonNull
public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);

onCreateViewHolder函数是用来绑定布局界面的,通过parent我们可以获取Context继而通过Id获取xml中的相应布局界面,通过viewType我们可以区分不同的布局界面来实现对不同界面的绑定。

onBindViewHolder(数据绑定)

1
2
3
4
5
/* @param holder The ViewHolder which should be updated to represent the contents of the
* item at the given position in the data set.
* @param position The position of the item within the adapter's data set.
*/
public abstract void onBindViewHolder(@NonNull VH holder, int position);

onBindViewHolder函数是我们进行数据绑定的位置,这里所给的holder也就是我们刚刚绑定的ViewHolder,position就是这些ViewHolder在所有ViewHolder集合中的位置。我们通过这两个参数就可以将传入Adapter中的数据,根据position所给的位置绑定到相应的ViewHolder中,简单地说,我们通过ViewHolder可以获得绑定布局的相关控件,比如TextView等,然后加上Adapter给的数据,进行setText()等操作,就完成数据与界面的绑定了。

小结

RecyclerView.Adapter是RecyclerView的内部类,我们不需要关心RecyclerView的内部实现,只是实现其内部类中的方法就可以实现数据与界面的绑定,其使用还是极为方便的。