二十三种设计模式(十六)--迭代器模式

迭代器模式

迭代器模式通过统一的接口解决元素遍历的问题, 屏蔽掉元素复杂的算法细节, 从而让调用者专注于实际业务的处理.

示例代码如下:

java 复制代码
// 具体的元素实现
class Message {
    String title;
    String Content;

    public Message(String title, String content) {
        this.title = title;
        Content = content;
    }
}

class Massager {
    private Message[] msgArr = new Message[5];
    private int size = 0;

    public boolean addMsg(Message msg) {
        if (size < 5) {
            msgArr[size++] = msg;
        } else {
            return false;
        }

        return true;
    }

    // 外部获取迭代器对象的入口
    MessageIterator createIterator() {
        return new MessageIterator();
    }

    // 较为通用的迭代器接口, 也可以再定义其他内容
    public interface iterator {
        Message next();
        boolean hasNext();
    }

    // 迭代器具体实现, 这里采用最简实现方式, 实际根据业务需求确定迭代逻辑
    // 比如采用ArrayList, HashMap等多种方式存储的数据
    // 下一条取用逻辑都在这里封装, 这一部分对调用端隐藏.
    class MessageIterator implements iterator {
        int curIdx = 0;

        @Override
        public Message next() {
            return msgArr[curIdx++];
        }

        @Override
        public boolean hasNext() {
            return curIdx < size;
        }
    }
}

在这个示例中, 迭代器继承自统一的接口, 意味着我们可以从不同的角度封装各种各样的迭代器, 可以有多个迭代器实现
createIterator迭代器创建方法, 在这个示例中仅返回了唯一的迭代器, 实际上根据业务需求, 可以采用参数方式返回多种迭代器

还有一点需要注意的是, 这个示例中, 将迭代器的接口和实现都是采用内部类的方式实现的, 这样也是实际业务中常用的写法, 好处在于迭代器中可以自由访问各种各样的集合容器, 比如示例中的msgArr

如果不采用这种方式, 那么在迭代器创建时要传入容器, 便于迭代器实现遍历逻辑.

外部调用

java 复制代码
public class IteratorPattern {
    public static void main(String[] args) {
        Massager msgr = new Massager();
        msgr.addMsg(new Message("新闻", "吴国近日将伐蜀"));
        msgr.addMsg(new Message("天气预报", "近日东吴有雨"));

        Massager.iterator iterator = msgr.createIterator();
        while (iterator.hasNext()) {
            Message msg = iterator.next();
            System.out.println(msg.title + ": " + msg.Content);
        }
    }
}

迭代器模式实现的必要性不止于此

比如我有如下业务需求:

我有一个名言锦句阅读应用, 客户端不断地从服务器获取未曾阅读过的诗词锦句, 服务端面对大量的用户请求, 进行了三级缓存设计, 以应对大量频繁的病发请求. 针对每一个用户, 首先在Redis中存储10条数据, 当Redis中数据取完时, 会从MongoDB中取用下一组10条数据, MongoDB中则存储100条数据. 当MongoDB中的数据取完时, 再从MySQL数据库中取用下一组100条数据.

而我们具体的业务逻辑中, 只会通过next()方法不断取用下一条数据, 并不关心下一条数据来自哪里.

针对上述诉求, 就可以采用迭代器模式来实现具体的数据取用逻辑

当业务扩展时, 比如我们更换了数据库, 采用PostgreSQL, 不再用MongoDB了, 也只更新迭代器的数据取用逻辑即可, 业务层的next()获取数据逻辑可以做到万年不变.

相关推荐
阿维的博客日记2 小时前
Hippo4j 线程池监控平台部署手册
java·spring boot·后端
C+++Python4 小时前
详细介绍一下Java泛型的通配符
java·windows·python
JosieBook4 小时前
【数据库】时序预测能力的分级进化:TimechoAI如何让每一类用户都能精准预见未来
java·开发语言·数据库
workflower5 小时前
使用大语言模型处理用户需求
大数据·人工智能·设计模式·重构·动态规划
一生了无挂5 小时前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json
李白的天不白6 小时前
使用 SmartAdmin 进行前后端开发
java·前端
swordbob6 小时前
Spring 单例 Bean 是线程安全的吗?
java·开发语言
2601_951643777 小时前
Python第一,Java跌出前三,C语言杀回来了
java·c语言·python·编程语言排行·技术趋势
IT 行者9 小时前
GitHub Spec Kit 实战(五):/speckit.tasks 怎么拆——Spec Kit 五部曲收官
java·ai编程·claude
(Charon)9 小时前
【C++ 面试高频基础:指针、引用、const、static、new/delete 总结】
java·开发语言