作者:小傅哥
博客:https://bugstack.cn - 原创系列专题文章
沉淀、分享、成长,让自己和他人都能有所收获!😄
相信相信的力量!
从懵懂的少年,到拿起键盘,可以写一个HelloWorld。多数人在这并不会感觉有多难,也不会认为做不出来。因为这样的例子,有老师的指导、有书本的例子、有前人的经验。但随着你的开发时间越来越长,要解决更复杂的问题或者技术创新,因此在网上搜了几天几夜都没有答案,这个时候是否想过放弃,还是一直坚持不断的尝试一点点完成自己心里要的结果。往往这种没有前车之鉴需要自己解决问题的时候,可能真的会折磨到要崩溃,但你要愿意执着、愿意倔强,愿意选择相信相信的力量,就一定能解决。哪怕解决不了,也可以在这条路上摸索出其他更多的收获,为后续前进的道路填充好垫脚石。
时间紧是写垃圾代码的理由?
拧螺丝?Ctrl+C、Ctrl+V?贴膏药一样写代码?没有办法,没有时间,往往真的是借口,胸中没用笔墨,才只能凑合。难道一定是好好写代码就浪费时间,拼凑CRUD就快吗,根本不可能的。因为不会,没用实操过,很少架构出全场景的设计,才很难写出优良的代码。多增强自身的编码(武术
)修为,在各种编码场景中让自己变得老练,才好应对紧急情况下的需求开发和人员安排。就像韩信一样有谋有略,才能执掌百万雄兵。
不要只是做个工具人!
因为日常的编写简单业务需求,导致自己像个工具人一样,日久天长的也就很少去深入学习更多技术栈。看见有工具、有组件、有框架,拿来就用用,反正没什么体量也不会出什么问题。但如果你想要更多的收入,哪怕是重复的造轮子,你也要去尝试造一个,就算不用到生产,自己玩玩总可以吧。有些事情只有自己经历过,才能有最深的感触,参与过实践过,才好总结点评学习。
bugstack虫洞栈
,回复源码下载
获取(打开获取的链接,找到序号18)工程 | 描述 |
---|---|
itstack-demo-design-15-00 | 开发树形组织架构关系迭代器 |
迭代器模式,常见的就是我们日常使用的iterator
遍历。虽然这个设计模式在我们的实际业务开发中的场景并不多,但却几乎每天都要使用jdk
为我们提供的list
集合遍历。另外增强的for循环虽然是循环输出数据,但是他不是迭代器模式。迭代器模式的特点是实现Iterable
接口,通过next
的方式获取集合元素,同时具备对元素的删除等操作。而增强的for循环是不可以的。
这种设计模式的优点是可以让我们以相同的方式,遍历不同的数据结构元素,这些数据结构包括;数组
、链表
、树
等,而用户在使用遍历的时候并不需要去关心每一种数据结构的遍历处理逻辑,从让使用变得统一易用。
在本案例中我们模拟迭代遍历输出公司中树形结构的组织架构关系中雇员列表
大部分公司的组织架构都是金字塔结构,也就这种树形结构,分为一级、二级、三级等部门,每个组织部门由雇员填充,最终体现出一个整体的树形组织架构关系。
一般我们常用的遍历就是jdk默认提供的方法,对list集合遍历。但是对于这样的偏业务特性较大的树形结构,如果需要使用到遍历,那么就可以自己来实现。接下来我们会把这个组织层次关系通过树形数据结构来实现,并完成迭代器功能。
在实现迭代器模式之前可以先阅读下java
中list
方法关于iterator
的实现部分,几乎所有的迭代器开发都会按照这个模式来实现,这个模式主要分为以下几块;
add
、remove
、iterator
等核心方法。Collection
继承。hasNext
、next
,会在具体的数据结构中写实现方式。除了这样通用的迭代器实现方式外,我们的组织关系结构树,是由节点和节点间的关系链构成,所以会比上述的内容多一些入参。
itstack-demo-design-15-02 └── src ├── main │ └── java │ └── org.itstack.demo.design │ ├── group │ │ ├── Employee.java │ │ ├── GroupStructure.java │ │ └── Link.java │ └── lang │ ├── Collection.java │ ├── Iterable.java │ └── Iterator.java └── test └── java └── org.itstack.demo.design.test └── ApiTest.java
迭代器模式模型结构
/** * 雇员 */ public class Employee { private String uId; // ID private String name; // 姓名 private String desc; // 备注 // ...get/set }
/** * 树节点链路 */ public class Link { private String fromId; // 雇员ID private String toId; // 雇员ID // ...get/set }
A to B
、B to C
、B to D
,以此描述出一套完整的树组织结构。public interface Iterator<E> { boolean hasNext(); E next(); }
java
的jdk
中提供的是一样的,这样也方面后续读者可以对照list
的Iterator
进行源码学习。hasNext
,判断是否有下一个元素、next
,获取下一个元素。这个在list
的遍历中是经常用到的。public interface Iterable<E> { Iterator<E> iterator(); }
Iterator
的获取,也就是后续在自己的数据结构中需要实现迭代器的功能并交给Iterable
,由此让外部调用方进行获取使用。public interface Collection<E, L> extends Iterable<E> { boolean add(E e); boolean remove(E e); boolean addLink(String key, L l); boolean removeLink(String key); Iterator<E> iterator(); }
Collection
,同时继承了另外一个接口Iterable
的方法iterator()
。这样后续谁来实现这个接口,就需要实现上述定义的一些基本功能;添加元素
、删除元素
、遍历
。<E, L>
,因为我们的数据结构一个是用于添加元素,另外一个是用于添加树节点的链路关系。public class GroupStructure implements Collection<Employee, Link> { private String groupId; // 组织ID,也是一个组织链的头部ID private String groupName; // 组织名称 private Map<String, Employee> employeeMap = new ConcurrentHashMap<String, Employee>(); // 雇员列表 private Map<String, List<Link>> linkMap = new ConcurrentHashMap<String, List<Link>>(); // 组织架构关系;id->list private Map<String, String> invertedMap = new ConcurrentHashMap<String, String>(); // 反向关系链 public GroupStructure(String groupId, String groupName) { this.groupId = groupId; this.groupName = groupName; } public boolean add(Employee employee) { return null != employeeMap.put(employee.getuId(), employee); } public boolean remove(Employee o) { return null != employeeMap.remove(o.getuId()); } public boolean addLink(String key, Link link) { invertedMap.put(link.getToId(), link.getFromId()); if (linkMap.containsKey(key)) { return linkMap.get(key).add(link); } else { List<Link> links = new LinkedList<Link>(); links.add(link); linkMap.put(key, links); return true; } } public boolean removeLink(String key) { return null != linkMap.remove(key); } public Iterator<Employee> iterator() { return new Iterator<Employee>() { HashMap<String, Integer> keyMap = new HashMap<String, Integer>(); int totalIdx = 0; private String fromId = groupId; // 雇员ID,From private String toId = groupId; // 雇员ID,To public boolean hasNext() { return totalIdx < employeeMap.size(); } public Employee next() { List<Link> links = linkMap.get(toId); int cursorIdx = getCursorIdx(toId); // 同级节点扫描 if (null == links) { cursorIdx = getCursorIdx(fromId); links = linkMap.get(fromId); } // 上级节点扫描 while (cursorIdx > links.size() - 1) { fromId = invertedMap.get(fromId); cursorIdx = getCursorIdx(fromId); links = linkMap.get(fromId); } // 获取节点 Link link = links.get(cursorIdx); toId = link.getToId(); fromId = link.getFromId(); totalIdx++; // 返回结果 return employeeMap.get(link.getToId()); } // 给每个层级定义宽度遍历进度 public int getCursorIdx(String key) { int idx = 0; if (keyMap.containsKey(key)) { idx = keyMap.get(key); keyMap.put(key, ++idx); } else { keyMap.put(key, idx); } return idx; } }; } }
new Iterator<Employee>
。雇员列表
、组织架构关系;id->list
。当元素添加元素的时候,会分别在不同的方法中向map
结构中进行填充指向关系(A->B),也就构建出了我们的树形组织关系。迭代器实现思路
@Test public void test_iterator() { // 数据填充 GroupStructure groupStructure = new GroupStructure("1", "小傅哥"); // 雇员信息 groupStructure.add(new Employee("2", "花花", "二级部门")); groupStructure.add(new Employee("3", "豆包", "二级部门")); groupStructure.add(new Employee("4", "蹦蹦", "三级部门")); groupStructure.add(new Employee("5", "大烧", "三级部门")); groupStructure.add(new Employee("6", "虎哥", "四级部门")); groupStructure.add(new Employee("7", "玲姐", "四级部门")); groupStructure.add(new Employee("8", "秋雅", "四级部门")); // 节点关系 1->(1,2) 2->(4,5) groupStructure.addLink("1", new Link("1", "2")); groupStructure.addLink("1", new Link("1", "3")); groupStructure.addLink("2", new Link("2", "4")); groupStructure.addLink("2", new Link("2", "5")); groupStructure.addLink("5", new Link("5", "6")); groupStructure.addLink("5", new Link("5", "7")); groupStructure.addLink("5", new Link("5", "8")); Iterator<Employee> iterator = groupStructure.iterator(); while (iterator.hasNext()) { Employee employee = iterator.next(); logger.info("{},雇员 Id:{} Name:{}", employee.getDesc(), employee.getuId(), employee.getName()); } }
22:23:37.166 [main] INFO org.itstack.demo.design.test.ApiTest - 二级部门,雇员 Id:2 Name:花花 22:23:37.168 [main] INFO org.itstack.demo.design.test.ApiTest - 三级部门,雇员 Id:4 Name:蹦蹦 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 三级部门,雇员 Id:5 Name:大烧 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:6 Name:虎哥 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:7 Name:玲姐 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:8 Name:秋雅 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 二级部门,雇员 Id:3 Name:豆包 Process finished with exit code 0
雇员 Id:2、雇员 Id:4...雇员 Id:3
1. 重学 Java 设计模式:实战工厂方法模式「多种类型商品不同接口,统一发奖服务搭建场景」
2. 重学 Java 设计模式:实战原型模式「上机考试多套试,每人题目和答案乱序排列场景」
3. 重学 Java 设计模式:实战桥接模式「多支付渠道(微信、支付宝)与多支付模式(刷脸、指纹)场景」
4. 重学 Java 设计模式:实战组合模式「营销差异化人群发券,决策树引擎搭建场景」
5. 重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」
6. 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」