设计模式讲解与代码实践(十七)——迭代器

本文来自李明子csdn博客(http://blog.csdn.net/free1985),商业转载请联系博主获得授权,非商业转载请注明出处!

1 目的

迭代器(Iterator)模式提供了不暴露对象内部状态的情况下依序遍历集合中元素的方法。
从应用场景来说,迭代器既可用于对集合中不可访问对象的保护也可用于对访问顺序的控制,本教程中的示例属于后者。
通常来说,遍历算法有两个可选的实现的位置。一个是在迭代器内部实现,本教程中的示例就属于这种情况;另一个是由集合自身实现,此时,迭代器仅对集合中对象的访问状态进行记录,迭代器仅作为游标使用。

2 基本形态

迭代器的基本形态如类图2-1所示。
图2-1  迭代器类图
图2-1 迭代器类图

3 参与者

结合图2-1,下面介绍各类在迭代器设计模式中扮演的角色。
3.1 Aggregate
Aggregate是集合接口,声明了迭代器对象创建方法CreateIterator。在JAVA中,已经定义了Aggregate接口,即java.lang.Iterable,迭代器对象的创建方法为iterator。
3.2 ConcreteAggregate
ConcreteAggregate是具体集合类,实现了Aggregate接口。在JAVA中,即为实现了java.lang.Iterable接口的类。其中,iterator方法返回的迭代器对象为具体迭代器类对象。
3.3 Iterator
Iterator是迭代器接口,声明了迭代器应实现的各方法。在JAVA中,已经定义了Iterator接口,即java.util.Iterator。通过对比不难发现,java.util.Iterator中声明的方法与2-1的类图中声明的方法不尽相同。类图中声明的迭代器可以重用,即可以通过First方法重置迭代器,且不包含任何对集合中元素的处理方法;java.util.Iterator不包含类似First这种重置迭代器的方法,且包含移除最后访问元素的方法remove。两种形式的设计理念略有不同,对应不同的应用场景各有利弊。笔者认为,从重用和封装的角度来讲,2-1类图中描述的接口更为合理和明晰。在实际应用中我们也可以根据实际需要声明自己的迭代器接口。
3.4 ConcreteIterator
ConcreteIterator是具体迭代器类,实现了Iterator接口。在JAVA中,即为实现了java.util.Iterator接口的类。为了实现对集合的遍历,ConcreteIterator类需要维护其要遍历的集合的引用。另外,拥有较好健壮性的迭代器应该可以支持遍历过程中集合元素的增删改等变化。
3.5 Client
Client是客户类,是迭代器模式的使用者。Client构建集合对象,并调用其CreateIterator方法创建迭代器对象。再使用迭代器对象遍历集合。

4 代码实践

下面我们用一个业务场景实例来进一步讲解迭代器的使用。
4.1 场景介绍
某银行柜台排队系统根据一定的策略对请求进行排队处理。请求按照VIP用户优先;存款业务优先;先到先处理三个条件排序。
以下各节将介绍该场景各类的具体实现及其在迭代器设计模式中所对应的参与者角色。
4.2 UserRequest
UserRequest是用户请求类,声明了用户请求中的编号、用户是否为VIP、请求业务类型及请求时间等属性。UserRequest在迭代器模式类图中未出现,它是集合中的元素。下面的代码给出了UserRequest的声明。

package demo.designpattern.iterator;

import java.util.Date;

/**
 * 用户请求
 * Created by LiMingzi on 2017/8/8.
 */
public class UserRequest{
    /**
     * 请求编号
     */
    private String requestCode;
    /**
     * 是否为vip用户
     */
    private boolean isVip;
    /**
     * 请求类型,0为存款;1为取款
     */
    private int type;
    /**
     * 请求时间
     */
    private Date requestDate;

    /**
     * 构造方法
     * @param requestCode 请求码
     * @param isVip 是否为vip
     * @param type 请求类型,0为存款;1为取款
     */
    public UserRequest(String requestCode, boolean isVip, int type) {
        this.requestCode = requestCode;
        this.isVip = isVip;
        this.type = type;
        this.requestDate=new Date();
    }

    /**
     * 获取请求码
     * @return 请求码
     */
    public String getRequestCode() {
        return requestCode;
    }

    /**
     * 获取是否为VIP
     * @return 是否为VIP
     */
    public boolean isVip() {
        return isVip;
    }

    /**
     * 获取请求类型
     * @return 请求类型,0为存款;1为取款
     */
    public int getType() {
        return type;
    }

    /**
     * 获取请求日期
     * @return 请求日期
     */
    public Date getRequestDate() {
        return requestDate;
    }

    @Override
    public String toString() {
        // 请求类型
        String typeString;
        if(type==0){
            typeString="存款";
        }else if(type==1){
            typeString="取款";
        }else{
            typeString="其他";
        }
        //  请求信息
        String requestInfo =  "请"+requestCode+"号";
        if(this.isVip){
            requestInfo+="VIP";
        }
        requestInfo+="顾客到柜台办理"+typeString+"业务-"+this.requestDate;
        return requestInfo;
    }
}

4.3 UserRequestList
UserRequestList是用户请求集合,提供了对UserRequest类型对象集合的维护。UserRequestList实现了java.lang.Iterable接口。对应于迭代器模式的参与者,UserRequestList是具体集合类ConcreteAggregate。下面的代码给出了UserRequestList的声明。

package demo.designpattern.iterator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 用户请求链表
 * Created by LiMingzi on 2017/8/8.
 */
public class UserRequestList implements Iterable {
    /**
     * 用户请求链表
     */
    private List<UserRequest> userRequests = new ArrayList<UserRequest>();
    /**
     * Returns an iterator over a set of elements of type T.
     *
     * @return an Iterator.
     */
    @Override
    public Iterator iterator() {
        return new UserRequestIterator(userRequests);
    }

    /**
     * 添加用户请求
     * @param userRequest 用户请求
     */
    public void add(UserRequest userRequest){
        userRequests.add(userRequest);
    }
}

上述代码中,15行,声明了用户请求对象集合userRequests,通过将其声明为私有成员且不提供对应的访问器和public操作方法,我们仅能通过30行声明的add方法向其添加用户请求。23行,返回的UserRequestIterator类型的迭代器对象是遍历userRequests的唯一方法。
4.4 UserRequestIterator
UserRequestIterator是用户请求迭代器,用于遍历UserRequestList维护的UserRequest对象集合。UserRequestIterator实现了java.util.Iterator接口。对应于迭代器模式的参与者,UserRequestIterator是具体迭代器类ConcreteIterator。下面的代码给出了UserRequestIterator的声明。

package demo.designpattern.iterator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * 用户请求迭代器
 * Created by LiMingzi on 2017/8/8.
 */
public class UserRequestIterator implements Iterator {
    /**
     * 用户请求链表
     */
    private List<UserRequest> userRequests;
    /**
     * 上一个请求
     */
    private UserRequest lastUserRequest;
    /**
     * 已遍历请求代码集合
     */
    private List<String>doneRequestCodes=new ArrayList<String>();

    /**
     * 构造方法
     * @param userRequests 用户请求链表
     */
    public UserRequestIterator(List<UserRequest> userRequests) {
        this.userRequests = userRequests;
    }

    /**
     * Returns <tt>true</tt> if the iteration has more elements. (In other
     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
     * rather than throwing an exception.)
     *
     * @return <tt>true</tt> if the iterator has more elements.
     */
    @Override
    public boolean hasNext() {
        return doneRequestCodes.size()<userRequests.size();
    }

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration.
     * @throws NoSuchElementException iteration has no more elements.
     */
    @Override
    public Object next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        // 下一个请求
        UserRequest nextUserRequest = null;
        for (UserRequest userRequest : userRequests) {
            // 该请求已遍历
            if(doneRequestCodes.contains(userRequest.getRequestCode())){
                continue;
            }
            // 还没有可比较请求
            if(nextUserRequest==null){
                nextUserRequest = userRequest;
                continue;
            }
            if(compareUserRequest(userRequest,nextUserRequest)>0){
                nextUserRequest=userRequest;
            }
        }
        lastUserRequest = nextUserRequest;
        doneRequestCodes.add(nextUserRequest.getRequestCode());
        return nextUserRequest;
    }

    /**
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to <tt>next</tt>.  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 <tt>remove</tt>
     *                                       operation is not supported by this Iterator.
     * @throws IllegalStateException         if the <tt>next</tt> method has not
     *                                       yet been called, or the <tt>remove</tt> method has already
     *                                       been called after the last call to the <tt>next</tt>
     *                                       method.
     */
    @Override
    public void remove() {
        if(lastUserRequest!=null){
            doneRequestCodes.remove(lastUserRequest.getRequestCode());
            userRequests.remove(lastUserRequest);
            lastUserRequest=null;
        }
    }

    /**
     * 比较用户请求优先级(优先级高先被响应)
     * 比较规则:VIP优先;其次存款优先;其次按请求时间早者优先
     * @param userRequest1 用户请求1
     * @param userRequest2 用户请求2
     * @return 用户请求1优先级高于用于请求2返回1;用户请求1优先级等于用于请求2返回0;用户请求1优先级低于用于请求2返回-1
     */
    private int compareUserRequest(UserRequest userRequest1,UserRequest userRequest2){
        // vip比较
        if(userRequest1.isVip()!=userRequest2.isVip()){
            if(userRequest1.isVip()){
                return 1;
            }else{
                return -1;
            }
        }
        // 请求类型比较
        if(userRequest1.getType()!=userRequest2.getType()){
            if(userRequest1.getType()<userRequest2.getType()){
                return 1;
            }else{
                return -1;
            }
        }
        // 日期比较
        return userRequest2.getRequestDate().compareTo(userRequest1.getRequestDate());
    }
}

上述代码中,20行,上一个请求对象lastUserRequest 用于实现93行接口方法remove。24行,已遍历请求代码集合doneRequestCodes防止请求被重复访问。借助于doneRequestCodes,53行实现next接口方法时,我们实际上在内部遍历了全部的元素(59行),这样就能够支持集合在遍历过程中的动态变化。108行比较用户请求优先级方法compareUserRequest实现了排序算法。
4.5 UserRequestMgmt
UserRequestMgmt是用户请求管理类,用于管理用户请求。对应于迭代器模式的参与者,UserRequestMgmt是客户Client。下面的代码给出了UserRequestMgmt的声明。

package demo.designpattern.iterator;

import java.util.Iterator;
import java.util.List;

/**
 * 用户请求管理器
 * Created by LiMingzi on 2017/8/8.
 */
public class UserRequestMgmt {
    /**
     * 用户请求集合
     */
    private UserRequestList userRequests;
    /**
     * 用户请求迭代器
     */
    private Iterator userRequestIterator;
    /**
     * 构造方法
     */
    public UserRequestMgmt() {
        this.userRequests = new UserRequestList();
        this.userRequestIterator=userRequests.iterator();
    }

    /**
     * 获取用户请求
     * @return 用户请求
     */
    public UserRequest getRequest(){
        // 用户请求
        UserRequest userRequest=null;
        if(userRequestIterator.hasNext()){
            userRequest=(UserRequest)userRequestIterator.next();
            userRequestIterator.remove();
        }
        return userRequest;
    }

    /**
     * 加入请求
     * @param userRequest 用户请求
     */
    public void putRequest(UserRequest userRequest){
        userRequests.add(userRequest);
    }
}

上述代码中,14行与18行分别声明了成员变量userRequests和userRequestIterator用来表示用户请求集合及其迭代器,它们均在构造方法中初始化。31行,getRequest方法,通过调用迭代器的next方法(35行)获取一个需要处理的请求,并将其从集合中移除(36行)。45行,加入请求方法putRequest通过调用用户请求集合的add方法(46行)实现用户请求的添加。
4.6 测试代码
为了测试本文中的代码,我们可以编写如下测试代码。测试代码中依次生成三个用户请求,之后响应一个用户请求,再添加两个用户请求,最后响应所有的用户请求。读者可以从测试代码中看到我们允许动态添加请求,请求的遍历也是按照既定策略执行的。为了使请求时间出现差异,代码中故意在每个请求后加入了1秒的延迟。

 /**
     * 迭代器测试
     */
    public static void iteratorTest() throws InterruptedException {
        // 用户请求管理
        UserRequestMgmt userRequestMgmt = new UserRequestMgmt();
        // 用户请求1
        UserRequest userRequest1=new UserRequest("001",false,1);
        userRequestMgmt.putRequest(userRequest1);
        sleep(1000);
        // 用户请求2
        UserRequest userRequest2=new UserRequest("002",false,0);
        userRequestMgmt.putRequest(userRequest2);
        sleep(1000);
        // 用户请求3
        UserRequest userRequest3=new UserRequest("003",false,0);
        userRequestMgmt.putRequest(userRequest3);
        sleep(1000);
        // 响应一次请求
        System.out.println(userRequestMgmt.getRequest());
        // 用户请求4
        UserRequest userRequest4=new UserRequest("004",true,2);
        userRequestMgmt.putRequest(userRequest4);
        sleep(1000);
        // 用户请求5
        UserRequest userRequest5=new UserRequest("005",true,0);
        userRequestMgmt.putRequest(userRequest5);
        sleep(1000);
        // 响应所有剩余请求
        while(true){
            // 当前请求
            UserRequest userRequest = userRequestMgmt.getRequest();
            if(userRequest ==null){
                break;
            }
            System.out.println(userRequest);
        }
    }

编译运行后,得到如下测试结果:
请002号顾客到柜台办理存款业务-Wed Aug 09 00:03:13 CST 2017
请005号VIP顾客到柜台办理存款业务-Wed Aug 09 00:03:16 CST 2017
请004号VIP顾客到柜台办理其他业务-Wed Aug 09 00:03:15 CST 2017
请003号顾客到柜台办理存款业务-Wed Aug 09 00:03:14 CST 2017
请001号顾客到柜台办理取款业务-Wed Aug 09 00:03:12 CST 2017

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
(1)UML样例源文件(8个样例文件) uml/uml.mdl //01.UML快速入门 uml/usecase.mdl //02.用例 uml/class.mdl //03.静态——类图、对象、包 uml/component.mdl //04.实现——组件与部署 uml/statechart.mdl //05.行为——状态 uml/activity.mdl //06.行为——活动 uml/sequence.mdl //07.交互——序列 uml/collaboration.mdl //08.交互——协作 (2)UML上机演练源文件(16个实例文件) uml/usecase_product.mdl //02.用例——企业产品生产销售管理系统 uml/class_login.mdl //03.类图和包——企业信息管理系统用户登录和注册模块 uml/component_emis.mdl //04.组件与部署——企业信息管理系统 uml/statechart_bug.mdl //05.状态——Bug管理系统 uml/statechart_atm.mdl //05.状态——ATM机存取款 uml/statechart_thread.mdl //05.状态——Java线程类Thread uml/activity_bug.mdl //06.活动——Bug管理系统 uml/activity_atm.mdl //06.活动——ATM机存取款 uml/activity_thread.mdl //06.活动——Java线程类Thread uml/sequence_bug.mdl //07.序列——Bug管理系统 uml/sequence_atm.mdl //07.序列——ATM机存取款 uml/sequence_tel.mdl //07.序列——打电话 uml/collaboration_bug.mdl //08.协作——Bug管理系统 uml/collaboration_atm.mdl //08.协作——ATM机存取款 uml/collaboration_tel.mdl //08.协作——打电话 uml/bug.mdl //09.综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/abstractfactory //11.2抽象工厂模式 pattern/src/creation/singleton //11.3单例模式 pattern/src/creation/builder //11.4建造者模式 pattern/src/creation/prototype //11.5原型模式 pattern/src/structure/adapter //12.1适配器模式 pattern/src/structure/decorator //12.2装饰器模式 pattern/src/structure/proxy //12.3代理模式 pattern/src/structure/facade //12.4外观模式 pattern/src/structure/bridge //12.5桥接模式 pattern/src/structure/composite //12.6组合模式 pattern/src/structure/flyweight //12.7享元模式 pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 pattern/src/behavior/chainofresponsibility//13.5责任链模式 pattern/src/behavior/command //13.6命令模式 pattern/src/behavior/memento //13.7备忘录模式 pattern/src/behavior/state //13.8状态模式 pattern/src/behavior/visitor //13.9访问者模式 pattern/src/behavior/mediator //13.10中介者模式 pattern/src/behavior/interpreter //13.11解释器模式 (4)SOA(12个程序包) soa/JAXWSHelloWorldServer.zip //15.JAX-WS服务端——HelloWorld实例 soa/JAXWSHelloWorldClient.zip //15.JAX-WS客户端——HelloWorld实例 soa/AxisHelloWorldServer.zip //16.Axis服务端——HelloWorld实例 soa/AxisHelloWorldClient.zip //16.Axis客户端——HelloWorld实例 soa/SCAJavazip //19.SCA实例——计算器实例 soa/SCAWSServer.zip //19.SCA服务端实例——HelloWorld实例 soa/SCAWSClient.zip //19.SCA客户端实例——HelloWorld实例 soa/OSGiHelloWorld.zip.zip //21.OSGi实例——HelloWorld实例 soa/demo.sql //24.SOA服务架构实战——企业信息管理系统数据库脚本 soa/ssh2.zip //24.SOA服务架构实战——企业信息管理系统SSH2代码 soa/EmisWeb.zip //24.SOA服务架构实战——企业信息管理系统SCA服务端 soa/EmisService.zip //24.SOA服务架构实战——企业信息管理系统Web端
好的,这是答案: 首先,需要定义一个接口,用于规范迭代器对象需要实现的方法: ``` public interface Iterator<T> { boolean hasNext(); // 判断是否还有下一个元素 T next(); // 获取下一个元素 } ``` 接下来需要定义一个可迭代对象的接口,用于规范可迭代对象需要实现的方法: ``` public interface Iterable<T> { Iterator<T> iterator(); // 获取迭代器对象 } ``` 接下来,我们使用一个示例来说明如何使用迭代器设计模式。定义一个迭代器内部类,并在外部类中实现Iterable接口: ``` import java.util.ArrayList; public class IterableClass<T> implements Iterable<T> { private ArrayList<T> list = new ArrayList<>(); // 添加元素 public void add(T t) { list.add(t); } // 获取元素 public T get(int index) { return list.get(index); } // 获取元素数量 public int size() { return list.size(); } // 获取迭代器对象 @Override public Iterator<T> iterator() { return new Iterator<T>() { private int index = 0; @Override public boolean hasNext() { return index < list.size(); } @Override public T next() { return list.get(index++); } }; } public static void main(String[] args) { IterableClass<String> iterableClass = new IterableClass<>(); iterableClass.add("hello"); iterableClass.add("world"); iterableClass.add("java"); // 使用for循环遍历元素 for (String str : iterableClass) { System.out.println(str); } } } ``` 最后我们运行main方法,得到以下结果: ``` hello world java ``` 以上是一个简单的迭代器设计模式Java代码示例,希望能够对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值