原創(chuàng)系列專題文章
沉淀、分享、成長,讓自己和他人都能有所收獲!😄
相信相信的力量!
從懵懂的少年,到拿起鍵盤,可以寫一個HelloWorld。多數(shù)人在這并不會感覺有多難,也不會認為做不出來。因為這樣的例子,有老師的指導、有書本的例子、有前人的經(jīng)驗。但隨著你的開發(fā)時間越來越長,要解決更復雜的問題或者技術創(chuàng)新,因此在網(wǎng)上搜了幾天幾夜都沒有答案,這個時候是否想過放棄,還是一直堅持不斷的嘗試一點點完成自己心里要的結果。往往這種沒有前車之鑒需要自己解決問題的時候,可能真的會折磨到要崩潰,但你要愿意執(zhí)著、愿意倔強,愿意選擇相信相信的力量,就一定能解決。哪怕解決不了,也可以在這條路上摸索出其他更多的收獲,為后續(xù)前進的道路填充好墊腳石。
時間緊是寫垃圾代碼的理由?
擰螺絲?Ctrl+C、Ctrl+V?貼膏藥一樣寫代碼?沒有辦法,沒有時間,往往真的是借口,胸中沒用筆墨,才只能湊合。難道一定是好好寫代碼就浪費時間,拼湊CRUD就快嗎,根本不可能的。因為不會,沒用實操過,很少架構出全場景的設計,才很難寫出優(yōu)良的代碼。多增強自身的編碼(武術
)修為,在各種編碼場景中讓自己變得老練,才好應對緊急情況下的需求開發(fā)和人員安排。就像韓信一樣有謀有略,才能執(zhí)掌百萬雄兵。
不要只是做個工具人!
因為日常的編寫簡單業(yè)務需求,導致自己像個工具人一樣,日久天長的也就很少去深入學習更多技術棧??匆娪泄ぞ?、有組件、有框架,拿來就用用,反正沒什么體量也不會出什么問題。但如果你想要更多的收入,哪怕是重復的造輪子,你也要去嘗試造一個,就算不用到生產(chǎn),自己玩玩總可以吧。有些事情只有自己經(jīng)歷過,才能有最深的感觸,參與過實踐過,才好總結點評學習。
bugstack蟲洞棧
,回復源碼下載
獲取(打開獲取的鏈接,找到序號18)工程 | 描述 |
---|---|
itstack-demo-design-15-00 | 開發(fā)樹形組織架構關系迭代器 |
迭代器模式,常見的就是我們?nèi)粘J褂玫?code>iterator遍歷。雖然這個設計模式在我們的實際業(yè)務開發(fā)中的場景并不多,但卻幾乎每天都要使用jdk
為我們提供的list
集合遍歷。另外增強的for循環(huán)雖然是循環(huán)輸出數(shù)據(jù),但是他不是迭代器模式。迭代器模式的特點是實現(xiàn)Iterable
接口,通過next
的方式獲取集合元素,同時具備對元素的刪除等操作。而增強的for循環(huán)是不可以的。
這種設計模式的優(yōu)點是可以讓我們以相同的方式,遍歷不同的數(shù)據(jù)結構元素,這些數(shù)據(jù)結構包括;數(shù)組
、鏈表
、樹
等,而用戶在使用遍歷的時候并不需要去關心每一種數(shù)據(jù)結構的遍歷處理邏輯,從讓使用變得統(tǒng)一易用。
在本案例中我們模擬迭代遍歷輸出公司中樹形結構的組織架構關系中雇員列表
大部分公司的組織架構都是金字塔結構,也就這種樹形結構,分為一級、二級、三級等部門,每個組織部門由雇員填充,最終體現(xiàn)出一個整體的樹形組織架構關系。
一般我們常用的遍歷就是jdk默認提供的方法,對list集合遍歷。但是對于這樣的偏業(yè)務特性較大的樹形結構,如果需要使用到遍歷,那么就可以自己來實現(xiàn)。接下來我們會把這個組織層次關系通過樹形數(shù)據(jù)結構來實現(xiàn),并完成迭代器功能。
在實現(xiàn)迭代器模式之前可以先閱讀下java
中list
方法關于iterator
的實現(xiàn)部分,幾乎所有的迭代器開發(fā)都會按照這個模式來實現(xiàn),這個模式主要分為以下幾塊;
add
、remove
、iterator
等核心方法。Collection
繼承。hasNext
、next
,會在具體的數(shù)據(jù)結構中寫實現(xiàn)方式。除了這樣通用的迭代器實現(xiàn)方式外,我們的組織關系結構樹,是由節(jié)點和節(jié)點間的關系鏈構成,所以會比上述的內(nèi)容多一些入?yún)ⅰ?/p>
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
}
/**
* 樹節(jié)點鏈路
*/
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
中提供的是一樣的,這樣也方面后續(xù)讀者可以對照list
的Iterator
進行源碼學習。hasNext
,判斷是否有下一個元素、next
,獲取下一個元素。這個在list
的遍歷中是經(jīng)常用到的。public interface Iterable<E> {
Iterator<E> iterator();
}
Iterator
的獲取,也就是后續(xù)在自己的數(shù)據(jù)結構中需要實現(xiàn)迭代器的功能并交給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()
。這樣后續(xù)誰來實現(xiàn)這個接口,就需要實現(xiàn)上述定義的一些基本功能;添加元素
、刪除元素
、遍歷
。<E, L>
,因為我們的數(shù)據(jù)結構一個是用于添加元素,另外一個是用于添加樹節(jié)點的鏈路關系。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);
// 同級節(jié)點掃描
if (null == links) {
cursorIdx = getCursorIdx(fromId);
links = linkMap.get(fromId);
}
// 上級節(jié)點掃描
while (cursorIdx > links.size() - 1) {
fromId = invertedMap.get(fromId);
cursorIdx = getCursorIdx(fromId);
links = linkMap.get(fromId);
}
// 獲取節(jié)點
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),也就構建出了我們的樹形組織關系。迭代器實現(xiàn)思路
@Test
public void test_iterator() {
// 數(shù)據(jù)填充
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", "秋雅", "四級部門"));
// 節(jié)點關系 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 設計模式:實戰(zhàn)工廠方法模式「多種類型商品不同接口,統(tǒng)一發(fā)獎服務搭建場景」
2. 重學 Java 設計模式:實戰(zhàn)原型模式「上機考試多套試,每人題目和答案亂序排列場景」
3. 重學 Java 設計模式:實戰(zhàn)橋接模式「多支付渠道(微信、支付寶)與多支付模式(刷臉、指紋)場景」
4. 重學 Java 設計模式:實戰(zhàn)組合模式「營銷差異化人群發(fā)券,決策樹引擎搭建場景」
5. 重學 Java 設計模式:實戰(zhàn)外觀模式「基于SpringBoot開發(fā)門面模式中間件,統(tǒng)一控制接口白名單場景」
6. 重學 Java 設計模式:實戰(zhàn)享元模式「基于Redis秒殺,提供活動與庫存信息查詢場景」