java/android 设计模式学习笔记(20)---迭代器模式

31 篇文章 1 订阅
31 篇文章 3 订阅

  我们这篇博客来介绍一下迭代器模式(Iterator Pattern),又称为游标(Cursor Pattern)模式,是行为型设计模式之一。迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如 Java 中的 List、Map、数组等,我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法。如果我们将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法,因为遍历状态的存储问题还不能对同一个容器同时进行多个遍历操作,如果我们不提供遍历方法而让使用者自己去实现,又会让容器的内部细节暴露无遗,正因于此,迭代模式应运而生,在客户访问类与容器体之间插入一个第三者——迭代器,很好地解决了上面所述的弊端。
  转载请注明出处:http://blog.csdn.net/self_study/article/details/52502709
  PS:对技术感兴趣的同鞋加群544645972一起交流。

设计模式总目录

  java/android 设计模式学习笔记目录

特点

  提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
  迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示,把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
  迭代器模式使用的场景也很简单:遍历一个容器对象时。

UML类图

  这里写图片描述
迭代器模式角色:

  • Iterator:迭代器接口
  • 迭代器接口负责定义、访问和遍历元素的接口。
  • ConcreteIterator:具体迭代器类
  • 具体迭代器类的目的主要是实现迭代器接口,并记录遍历的当前位置。
  • Aggregate:容器接口
  • 容器接口负责提供创建具体迭代器角色的接口。
  • ConcreteAggregate:具体容器类
  • 具体迭代器角色与该容器相关联。
  • Client:客户类
  据此我们可以写出迭代器模式的通用代码:
迭代器类:
Iterator.class

public interface Iterator<T> {
    boolean hasNext();

    T next();
}

ConcreteIterator.class

public class ConcreteIterator<T> implements Iterator<T>{
    private List<T> list;
    private int cursor = 0;

    public ConcreteIterator(List<T> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return cursor != list.size();
    }

    @Override
    public T next() {
        T obj = null;
        if (this.hasNext()) {
            obj = this.list.get(cursor++);
        }
        return obj;
    }
}

容器类:
Aggregation.class

public interface Aggregation<T> {

    void add(T obj);

    void remove(T obj);

    Iterator<T> iterator();
}

ConcreteAggregation.class

public class ConcreteAggregation<T> implements Aggregation<T>{
    private List<T> list = new ArrayList<>();

    @Override
    public void add(T obj) {
        list.add(obj);
    }

    @Override
    public void remove(T obj) {
        list.remove(obj);
    }

    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<>(list);
    }
}

客户端代码

public class Client {
    public static void main(String args[]) {
        Aggregation<String> a = new ConcreteAggregation<>();
        a.add("a");
        a.add("b");
        a.add("c");
        Iterator<String> iterator = a.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
        }
    }
}

最后结果就是遍历了一遍:

abc
Process finished with exit code 0

示例与源码

  迭代器这个模式对于很多开发者来说几乎不会自己去实现一个迭代器,但是我们平时使用的频率不会低,在 Android 中,除了各种数据结构体,如 List、Map 等所包含的迭代器外,数据库查询的 Cursor 也是一个迭代器。
  我们这里就简单分析一下 ArrayList 的 Iterator 源码:
Iterator.class

public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();

    /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.  The behavior of an iterator
     * is unspecified if the underlying collection is modified while the
     * iteration is in progress in any way other than by calling this
     * method.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
    void remove();
}

ArrayList.Itr.class

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

这就是 ArrayList 迭代器的具体实现,从源码中我们可以看到有一个 checkForComodification() 函数,抛出的异常 ConcurrentModificationException 应该很多人认识,如果 modCount 不等于 expectedModCount,则抛出 ConcurrentModificationException 异常,一般情况下出现在遍历的同时调用了 ArrayList.remove 等操作对数据集合进行了更改,例如多线程中当一个线程删除了元素,由于 modCount 是 AbstarctList 的成员变量,因此可能会导致在其他线程中modCount 和 expectedModCount 值不等。

总结

  对于迭代模式来说,其自身优点很明显:

  • 迭代子模式简化了聚集的接口,迭代子具备了一个遍历接口,这样聚集的接口就不必具备遍历接口;
  • 每一个聚集对象都可以有一个或多个迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。因此,一个聚集对象可以同时有几个迭代在进行之中;
  • 由于遍历算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化。
而其缺点就是对类文件的增加。其实迭代模式发展至今,几乎每一种高级语言都有相应的内置实现,对于开发者来说,已经很少会去由自己来实现迭代器了,因此,对于迭代器模式我们更多地是在于了解而非应用。

源码下载

  https://github.com/zhaozepeng/Design-Patterns/tree/master/IteratorPattern

引用

http://blog.csdn.net/jason0539/article/details/45070441
https://en.wikipedia.org/wiki/Iterator_pattern

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
在JWS SOAP Web Service中,可以使用Handler实现过滤器/拦截器的效果,对接口请求和响应进行处理。 Handler是Java EE中的一个标准接口,用于处理Web Service请求和响应。在JWS SOAP Web Service中,Handler可以对请求和响应进行处理,类似于Servlet中的过滤器和拦截器。 Handler可以在请求到达Web Service之前或者响应离开Web Service之后进行处理,可以对SOAP消息的头和体进行处理,可以修改SOAP消息中的内容,可以设置SOAP消息的属性等。 在JWS SOAP Web Service中,使用Handler需要完成以下步骤: 1. 创建Handler类,实现javax.xml.ws.handler.Handler接口,并实现其方法。 2. 在Web Service实现类中,使用@HandlerChain注解指定Handler链的位置和名称。 3. 在Handler链的配置文件中,指定Handler类的位置和名称,并指定Handler类的处理顺序。 示例代码如下: Handler类: ```java public class MyHandler implements SOAPHandler<SOAPMessageContext> { public boolean handleMessage(SOAPMessageContext context) { Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outbound) { System.out.println("Handle outbound message."); } else { System.out.println("Handle inbound message."); } return true; } public boolean handleFault(SOAPMessageContext context) { System.out.println("Handle message fault."); return true; } public void close(MessageContext context) { System.out.println("Close handler."); } public Set<QName> getHeaders() { return null; } } ``` Web Service实现类: ```java @WebService @HandlerChain(file = "handler-chain.xml") public class MyWebService { @WebMethod public String sayHello(String name) { return "Hello, " + name + "!"; } } ``` Handler链配置文件handler-chain.xml: ```xml <?xml version="1.0" encoding="UTF-8"?> <handler-chains xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/handler-chains_1_0.xsd"> <handler-chain> <handler> <handler-class>com.example.MyHandler</handler-class> </handler> </handler-chain> </handler-chains> ``` 在上面的示例中,我们创建了一个MyHandler类,实现了javax.xml.ws.handler.Handler接口,并实现了handleMessage、handleFault、close和getHeaders方法。在MyWebService类中,使用@HandlerChain注解指定了Handler链的位置和名称。在handler-chain.xml中,指定了MyHandler类的位置和名称,并指定了处理顺序。 当Web Service被调用时,MyHandler类会对请求和响应进行处理,并输出相关信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值