原本是周更的頻率, 由於真實的"小光"真實地逃離了北京, 回了武漢, 回了老家, 處理了一些私人事務. 也就有快一個月時間沒有更新了, 抱歉.javascript
年終總結也都沒有時間寫, 抽空寫這麼一篇, 提早祝你們新年快樂, 過年回家路上平安順利.java
上集講到, 小光統一了各個分店的製做熱乾麪的流程, 而且引入模板方法在不改變熱乾麪的製做流程基礎上能夠定製其中某些步驟. 經過這些措施, 小光熱乾麪的品牌性也是更加深刻人心, 生意紅紅火火. git
此時的小光, 有了更多的時間去思考公司的前程, 他認爲, 一個良好的有序的組織架構是公司發展的必要點. 而此時, 小光也有以爲是時候梳理下公司的組織架構了.github
全部示例源碼已經上傳到Github, 戳這裏架構
小光參考了當前不少公司的一些架構方式, 根據分店, 職責簡單梳理了下目前小光熱乾麪的架構:
app
整個就是一個樹形結構.ide
梳理完組織關係後, 小光以爲有必要設計一套系統來管理這個關係圖, 以便後續能方便的查看和管理這個架構, 並能很清晰地講解給新員工.ui
一開始, 小光並無想太多, 按照不一樣的層級, 分別建立了總公司, 分店, 部門三個類:this
// 部門
public class Department {
private String name;
public Department(String name) {
this.name = name;
}
@Override
public String toString() {
return "部門:" + name;
}
}
// 分店
public class BranchOffice {
private String name;
public BranchOffice(String name) {
this.name = name;
}
private List<Department> departments = new ArrayList<>();
public void add(Department sub) {
departments.add(sub);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("分公司:" + name);
for (Department dept : departments) {
builder.append(" - " + dept.toString());
}
return builder.toString();
}
}
// 總公司
public class HeadOffice {
private String name;
public HeadOffice(String name) {
this.name = name;
}
private List<Department> departments = new ArrayList<>();
public void add(Department sub) {
departments.add(sub);
}
private List<BranchOffice> branches = new ArrayList<>();
public void add(BranchOffice branchOffice) {
branches.add(branchOffice);
}
public void print() {
System.out.println("總公司:" + name);
for (BranchOffice branch : branches) {
System.out.println(" - " + branch);
}
for (Department dept : departments) {
System.out.println(" - " + dept);
}
}
}複製代碼
利用這些層次的類來組成小光的組織架構:spa
public class XiaoGuang {
public static void main(String[] args) {
HeadOffice headOffice = new HeadOffice("小光熱乾麪");
Department financeDept = new Department("財務部");
Department strategyDept = new Department("策劃部");
BranchOffice ov = new BranchOffice("光谷分店");
ov.add(financeDept);
ov.add(strategyDept);
BranchOffice huashan = new BranchOffice("花山分店");
huashan.add(financeDept);
huashan.add(strategyDept);
headOffice.add(financeDept);
headOffice.add(strategyDept);
headOffice.add(ov);
headOffice.add(huashan);
headOffice.print();
}
}複製代碼
結果以下, 達到要求:
總公司:小光熱乾麪
- 分公司:光谷分店 - 部門:財務部 - 部門:策劃部
- 分公司:花山分店 - 部門:財務部 - 部門:策劃部
- 部門:財務部
- 部門:策劃部複製代碼
看着這新鮮出爐的架構程序, 小光總以爲哪兒不對勁兒. 畢竟小光是歷經了北上廣各類類型公司的人才啊, 回想起上班敲代碼的日子, 小光想起了哪兒不妥了. 公司總會發展, 發展過程當中總會有一些戰略調整, 從而致使公司部門的各類變化.
目前小光設計的組織架構是三層架構, 可是隨着公司的發展壯大, 頗有可能層級會變得更多. 好比說, 總部的採購部壯大了, 可能會增長下一級的食材採購部和設備採購部. 甚至可能如今的層級還會隨着公司的戰略調整而升降. 例如, 若是分店開到別的城市了, 可能會在總部和分店之間插入一層"子公司"來分別管理各地的分店. 以下:
那麼就出現了一個咱們一直在強調的問題: 有些東西可能會一直有變化, 而咱們從產品角度確定會想要擁抱變化, 然而代碼層面上咱們又不想修改代碼(修改原有代碼意味着還有對原有邏輯負責).
那應該怎麼辦呢? 有沒有更好的方式來表達這種樹形的組織架構關係呢? 以便可以很容易地擴展層次呢?
小光又回想起了本身的碼農時代, 回想當年這種問題的解決方案:
既然是由於變化, 擴展而引發的問題, 咱們最重要是要先找出系統中可變和不可變的部分, 封裝不可變(使其修改關閉), 擁抱可變(使其擴展開放).
那麼具體到這個組織系統架構的問題, 又該怎麼作呢?
小光可不想每增長一個層級都要從新爲其增長一個類, 而後改變原有系統. 特別是有些狀況下, 曾加的類(子公司)中可能會包含分店和本身的部門. 隨着類別的增長, 每次增長一個層級將會愈來愈難.
小光想到着, 忽然想到:
每一個部門/分店/子公司乃至總公司不都是部門的集合嗎?
部門可能有下屬部門, 可能沒有
分店下有部門
子公司下有分店, 可能還有本身的部門
總公司下有子公司, 分店, 本身的部門
因此說, 全部實體(總公司/子公司/分店/部門)實際上都是由部門組成的. 這些實體也均可以看着是一個部門.
想到作到:
首先定義出基礎的部門:
public class Department {
private String name;
public Department(String name) {
this.name = name;
}
private List<Department> subDepartments = new ArrayList<>();
public void add(Department sub) {
subDepartments.add(sub);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(name);
for (Department dept : subDepartments) {
builder.append("\n");
builder.append(" - " + dept.toString());
}
return builder.toString();
}
}複製代碼
來看下, 利用Department這一個類別怎麼搭建組織:
public class XiaoGuang {
public static void main(String[] args) {
Department financeDept = new Department("財務部");
Department strategyDept = new Department("策劃部");
Department ovBranchOffice = new Department("光谷分店");
ovBranchOffice.add(financeDept);
ovBranchOffice.add(strategyDept);
Department huashanBranchOffice = new Department("花山分店");
huashanBranchOffice.add(financeDept);
huashanBranchOffice.add(strategyDept);
Department wuhanChildOffice = new Department("武漢子公司");
wuhanChildOffice.add(ovBranchOffice);
wuhanChildOffice.add(huashanBranchOffice);
Department changshaChildOffice = new Department("長沙子公司");
Department xiaoguang = new Department("小光熱乾麪");
xiaoguang.add(wuhanChildOffice);
xiaoguang.add(changshaChildOffice);
xiaoguang.add(financeDept);
xiaoguang.add(strategyDept);
System.out.println(xiaoguang);
}
}複製代碼
輸出以下
小光熱乾麪
- 武漢子公司
- 光谷分店
- 財務部
- 策劃部
- 花山分店
- 財務部
- 策劃部
- 長沙子公司
- 財務部
- 策劃部複製代碼
輸出稍有調整, 以顯示直觀的層級. 你們能夠自行修改下代碼, 來給department加入level屬性, 以便輸出更完美的結構.
到此, 咱們算是解決了組織架構的問題了, 之後不論是增長了什麼層級, 咱們都只須要使用Department來表示便可, 而無需增長一個類了.
照例, 咱們來縷縷小光設計的這套系統的"類關係":
結構至關簡單, 實際上就是一個類, 其中關鍵的是: 這個類中有一個list屬性(subDepartments)包含的是一組該類. 有點遞歸的感受.
這個就是咱們今天想說的 --- 組合模式
組合模式
又叫部分總體模式,經過組合的方式, 建立一個包含了一組本身的對象組(List) 的類(Department). 從而達成了用一個類來遞歸地表示一個總體.組合模式一般用來解決樹形結構的表達問題, 例如本例中的組織結構.
所謂組合的方式, 就是建立一個包含了一組本身的對象組的類
注: 咱們這裏實現的相對簡單, 旨在說明模式的形式.
實際場景中, Department多是一個抽象的, 例若有一個抽象方法來執行該部門的職責, 有不一樣的具體部門實現來實現其職責. 從而有不一樣的"Department實現"來組合另外一個大的Department節點.
前面說到, 組合模式一般用來處理樹形結構的表達問題. 而咱們的用戶界面實現一般就是一個UI元素的節點樹. 例如HTML中的div中可能有button, 還會有其餘div層級, 依次往下; Java SE中的界面實現AWT和Swing包也處處是組合模式的體現; Android中的View體系, View和ViewGroup, Layout層級樹也都是組合模式的體現.
在此咱們以Android的View體系爲例, 簡單描述下.
衆所周知, Android的界面實際上就是一顆大樹, Hierarchy Viewer中展現的就是一個樹形結構. 咱們來看下Android是怎麼利用組合模式實現的.
以下:
關於View的體系, 在此不細述了.
搭建好彈性可擴展的組織架構體系, 小光又開始將眼光轉移到市場, 轉移到業務了, 準備着新年大展拳腳~