设计模式——适配器模式

适配器模式用来将一个类的接口转换为另一种接口,使本来因为接口不兼容而不能一起工作的类可以一起工作。一个很常见的例子就是如果想要手机和U盘通信,但是两者没有通用的接口,就需要通过OTG线来连接,OTG线一端是micro-usb接口,另一端是USB接口,分别对应了手机和U盘的接口。

而具体的实现有两种,一种叫类适配器模式,另一种叫对象适配器模式。

类适配器模式

Target是客户需要的接口,Adapter是适配器类,来做一个转换,Adaptee是需要适配的类,最终的目的是想要客户可以使用它。图中其实应该画上客户,客户通过调用Target接口,就可以使用Adaptee类。

Adapter通过继承实现了Target的接口,Adapter和Adaptee如何产生联系,有两种方式,一是使用组合的方式,即把Adaptee对象放在Adapter中,即类适配器模式;另一种方式是多重继承,即让Adapter也继承Adaptee。

对象适配器模式

public class Client {

    public static void main(String[] args){
        Target target = new Adapter(new Adaptee());
        target.method1();
    }
}

interface Target{
    public void method1();
}

class Adaptee{
    public void method2(){
        System.out.println("execute Adaptee.method2()");
    }
}

class Adapter implements Target{
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }

    @Override
    public void method1(){
        this.adaptee.method2();
    }
}

 Client通过Adapter类的Target接口调用了Adaptee对象。

Arrays.asList()

jdk中的Arrays.asList()方法用到了适配器模式。

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

假如现在有一个数组,或者一系列元素,然而需要一个List对象,这时就可以使用这个方法得到一个固定长度的list(长度即数组长度)。在这里用到了可变参数,实际上是java的一个语法糖,实际上还是通过数组来实现。这个方法返回的是一个ArrayList对象,通过数组a来进行初始化。但是需要注意的是,这个ArrayList并不是java.util.ArrayList,而是在Arrays中实现的一个内部类。

传入到构造函数中的对象数组,进行了一个Null Pointer的检查,如果是null则会抛出异常,如果不是,则赋值给了a。这样,内部类对象的成员a实际指向了作为参数传入的对象数组,对a的操作,实际上就是对数组的操作。但是观察这个内部类的成员函数,并没有add、remove方法,实际上也很好理解,因为本质上维护的还是一个数组,这些方法本来也无法实现。

总结一下,List为客户需要的类,数组为被适配对象,通过Arrays.ArrayList作为适配器,实现了接口转换,但背后还是数组。

这样一来,得到了Arrays.asList()的几个特点:

1. 参数不能是基本类型,因为用到了泛型,必须传入一个对象类型。

2. 方法返回的List,是与数组链接起来的,即更新一处,则同时更新,因为背后本来就是一个数组

3. 不能使用集合修改的相关方法 add/remove/clear,原因与第二条相同。

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return Arrays.copyOf(a, a.length, Object[].class);
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }

        @Override
        public Iterator<E> iterator() {
            return new ArrayItr<>(a);
        }
    }

参考

适配器模式

【设计模式】Adapter

Arrays.asList()方法/适配器模式

浅谈Arrays.asList()方法的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值