Java设计模式 -- 适配器模式

我们先来明确一下 适配器模式有三种,分别是 类适配器模式、对象适配器模式、接口适配器模式

接下来不打算直接看这些模式的定义以及实例源码,我们直接从问题出发。

假如有如下类

public class ViewController {
    public void getView() {
        System. out.println("This is Original getView() method!" );
    }
}

现在有新的需求,需要转换这个类,如果直接修改这个类可能会带来不必要的风险,那么如何在保持该类不动的情况下转换这个类呢?

方法大体上有两种

  • 其一是 继承(泛化)
  • 其二是 聚合

我们不说上面两种方法有什么优缺点,先来看看如何实现

##类适配器模式

定义接口抽取功能方法

public interface Adapter {
    public void getView();
    public void getCount();
}

接着定义继承类,一并实现该功能接口

public class BaseAdapter extends ViewController implements Adapter {
    @Override
    public void getView() {
        super.getView();
    }

    @Override
    public void getCount() {
        System. out.println("This is Adapter extends ViewController getCount() method!");

    }
}

然后 就可以在 测试用例中体现多态了

public class TestCase {
    public static void main(String[] args) {

        /*
         * Call Adapter Method;
         */

        Adapter adapter = new BaseAdapter();
        adapter.getView();
        adapter.getCount();

    }
}

上面这种解决方式就是设计模式上所说的 类适配器模式.

接下来看看第二种实现方法

对象适配器/装饰器模式

定义一个聚合类

public class Wrapper implements Adapter {
    private ViewController source;

    public Wrapper( final ViewController source ) {
        this.source = source;
    }

    @Override
    public void getView() {
        source.getView();
    }

    @Override
    public void getCount() {
        System. out.println("This is wrapper adapter method!" );
    }
}

构造器 需要传入ViewController 的实例

然后直接看测试用例

public class TestCase {

    public static void main(String[] args) {

        /*
         * Call Original Method;
         */
        ViewController source = new ViewController();
        source.getView();

        /*
         * Call Wrapper Adapter Method;
         */

        Adapter wrapper = new Wrapper(source);
        wrapper.getView();
        wrapper.getCount();

    }
}

这种实现思路在设计模式上叫做 对象适配器模式.

当然 我们也可以将上面的Wrapper类做如下调整

public class Wrapper implements Adapter {

    private ViewController source;

    public Wrapper( final ViewController source ) {
        this.source = source;
    }

    @Override
    public void getView() {
        System. out.println("Before getview() method call, you can do something here before getview method");
        source.getView();
        System. out.println("After getview() method call, you can do something here after getview method");
       
    }

    @Override
    public void getCount() {
        System. out.println("This is wrapper adapter method!" );
    }
}

这个时候我们也可以称之为 装饰器模式, Android中比较常见的装饰器模式是 ContextWrapper 这个类

通过上面这个例子,可能感觉到 装饰器模式和适配器模式 不是一样的吗?干嘛还弄两个设计模式?

其实 装饰模式和适配器模式都有一个别名,就是包装模式,但是这两个模式是很不一样的。适配器模式的用意是要改变所考虑对象的接口,将其转换成所需要的形式,而装饰模式的用意是保持接口,只是为了扩展功能,一个是转换,一个是扩展。

小结一下:
上面两种实现思路 迥然不同 对象适配器可以很好的解决类适配器模式中遇到的兼容问题, 他们俩孰优孰劣 还需视不同的情况区别对待。

接口适配器模式

接下来我们看一下Android中广为人知的Adapter源码:

public interface Adapter {
    
    void registerDataSetObserver(DataSetObserver observer);
    void unregisterDataSetObserver(DataSetObserver observer);
    int getCount();  
    Object getItem(int position);
    long getItemId( int position );
    boolean hasStableIds();
    View getView(int position, View convertView , ViewGroup parent);
    int getItemViewType( int position );
    int getViewTypeCount();
    boolean isEmpty();
}

再看一下它的子接口

public interface SpinnerAdapter extends Adapter {
    
    public View getDropDownView( int position , View convertView, ViewGroup parent);
}

public interface ListAdapter extends Adapter {
    public boolean areAllItemsEnabled();
    boolean isEnabled( int position );
}

接着看它的实现抽象类

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

    public boolean hasStableIds() {
        return false ;
    }
   
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer );
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer );
    }
   
    /**
     * Notifies the attached observers that the underlying data has been changed
     * and any View reflecting the data set should refresh itself.
     */
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

    /**
     * Notifies the attached observers that the underlying data is no longer valid
     * or available. Once invoked this adapter is no longer valid and should
     * not report further data set changes.
     */
    public void notifyDataSetInvalidated() {
        mDataSetObservable.notifyInvalidated();
    }

    public boolean areAllItemsEnabled() {
        return true ;
    }

    public boolean isEnabled(int position) {
        return true ;
    }

    public View getDropDownView( int position , View convertView, ViewGroup parent) {
        return getView(position , convertView , parent );
    }

    public int getItemViewType(int position) {
        return 0;
    }

    public int getViewTypeCount() {
        return 1;
    }
   
    public boolean isEmpty() {
        return getCount() == 0;
    }
}

看完上面的这个BaseAdapter以后,到这我们可能不知道这个BaseAdapter类究竟有啥作用,继续往下看

public class ScheduleAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Object getItem( int position ) {
        // TODO Auto-generated method stub
        return null ;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView( int position , View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        return null ;
    }
}

这么一个适配器类相信大家都不陌生,从这个类是不是就看出BaseAdapter类的好处了,如果还看不出来,最简单的办法是自己写个Adapter类 不经过BaseAdapter 就会像下面这样

public class ScheduleAdapter implements ListAdapter, SpinnerAdapter {

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        // TODO Auto-generated method stub
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        // TODO Auto-generated method stub
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Object getItem( int position ) {
        // TODO Auto-generated method stub
        return null ;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return false ;
    }

    @Override
    public View getView( int position , View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        return null ;
    }

    @Override
    public int getItemViewType(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean isEmpty() {
        // TODO Auto-generated method stub
        return false ;
    }

    @Override
    public View getDropDownView( int position , View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        return null ;
    }

    @Override
    public boolean areAllItemsEnabled() {
        // TODO Auto-generated method stub
        return false ;
    }

    @Override
    public boolean isEnabled(int position) {
        // TODO Auto-generated method stub
        return false ;
    }
}

是不是原先接口的每个方法都需要一一实现,而大部分接口方法是不需要从新实现一遍的,因此BaseAdapter这个抽象类就充当了中间适配的角色

上面这个就是设计模式中的接口适配器模式

用一张图形象的表述如下:

此处输入图片的描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值