设计模式:适配器模式

适配器模式是一种设计模式,用于解决接口不兼容问题,通过创建一个适配器来使原有类符合新接口。它分为类适配和对象适配,常见于系统需要使用现有类但接口不匹配的情况。在Android中,如ListView、RecyclerView等,适配器用于将数据源转换为可显示的视图,实现解耦和高度定制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、定义:

        将某一些对象转换为需要的适配的对象

        分为类适配和对象适配

        为了解决接口不兼容问题的。比如给你的接口和你现有的接口对接不起来、旧的数据和新的数据接对接不起来等等。

        遇到这种问题,如果没有源码,或者不愿意修改各自的接口,这种情况往往会使用一个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);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值