一、定义:
将某一些对象转换为需要的适配的对象
分为类适配和对象适配
为了解决接口不兼容问题的。比如给你的接口和你现有的接口对接不起来、旧的数据和新的数据接对接不起来等等。
遇到这种问题,如果没有源码,或者不愿意修改各自的接口,这种情况往往会使用一个Adapter,对两个接口做兼容,在不修改原接口的情况下,达到目的。
二、使用场景
- 接口不兼容,系统需要使用现有的类,而类的接口不符合系统需要
- 需要一个统一的输出接口,而输入端的类型不可预知
- 想要建立一个可以重复使用的类,用于一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。
三、角色
- Target:适配器接口,即目标角色,定义把其他类转换为何种接口,也就是客户端期望的接口
- Adaptee:即源角色,一般是已存在的类,需要适配新的接口
- Adapter:具体适配器,实现适配器接口,把源角色接口转换为目标角色期望的接口
四、优缺点
优点:
- 复用性:系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 透明:客户端可以调用同一端口,因而对客户端来说是透明的。这用做更简单并且更直接。
- 扩展性:在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
- 解耦性:将目标和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改源代码。
缺点:
- 过多的使用适配器,会让系统非常凌乱,不易进行整体把握。
五、模板代码
/**
* 目标接口:Target
*/
interface Target {
void request();
}
/**
* 类源:Adaptee
*/
class Adaptee {
void selfRequest() {
System.out.println("selfRequest");
}
}
/**
* 类的适配器模式
*/
class Adapter extends Adaptee implements Target {
@Override
public void request() {
this.selfRequest();
}
}
/**
* 对象的适配器模式
*/
class Adapter1 implements Target {
private Adaptee adaptee;
public Adapter1(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.selfRequest();
}
}
public class Client {
public static void main(String[] args) {
Adapter adapter = new Adapter();
adapter.request();
Adapter1 adapter1 = new Adapter1(new Adaptee());
adapter1.selfRequest();
}
}
六、Android系统中的使用
ListView、GridView、RecyclerView都使用Adapter,
dapter的作用都一样,把高度定制化的item view和ListView分开。item view通过一个Adapter和ListView联系到一起。解耦而不失高度可定制。
ListView只关心它的每个ItemView,而不关心这个ItemView具体显示的是什么。而我们的数据源存放的是要显示的内容,它保存了每一个ItemView要显示的内容。ListView和数据源之间没有任何关系,这时候,需要通过适配器,适配器提供getView方法给ListView使用,每次ListView只需提供位置信息给getView函数,然后getView函数根据位置信息向数据源获取对应的数据,根据数据返回不同的View。
recyclerview 从后台拿到的是列表数据,RecyclerView里面显示的是View,两者不匹配
七、ListView简单实现
1.目标接口
public interface AdapterTarget { int getCount(); View getView(int position,ViewGroup parent); }
2.对象适配器,将数据源转换为View
public class ListAdapter implements AdapterTarget { private List<String> mItems; private Context context; public ListAdapter(List<String> items, Context context){ this.mItems = items; this.context = context; } @Override public int getCount() { return mItems.size(); } @Override public View getView(int position, ViewGroup parent) { TextView itemView = (TextView) LayoutInflater.from(context) .inflate(R.layout.item_main,parent,false); itemView.setText(mItems.get(position)); return itemView; } }
3.listView
public class ListView extends ScrollView{ private LinearLayout mContainer; private AdapterTarget mAdapter; public ListView(Context context) { this(context,null); } public ListView(Context context, AttributeSet attrs) { this(context, attrs,0); } public ListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContainer = new LinearLayout(context); mContainer.setOrientation(LinearLayout.VERTICAL); addView(mContainer,0); } @Override public void addView(View child) { mContainer.addView(child); } public void setAdapter(ListAdapter adapter) { this.mAdapter = adapter; //不考虑复用、缓存等。简单实现 int count = mAdapter.getCount(); for (int i=0;i<count;i++){ View childView = mAdapter.getView(i,mContainer); addView(childView); } } }