梳理公司的組織架構(gòu)---組合模式

cover

題外話

本來是周更的頻率, 因?yàn)檎鎸?shí)的"小光"真實(shí)地逃離了北京, 回了武漢, 回了老家, 處理了一些私人事務(wù). 也就有快一個(gè)月時(shí)間沒有更新了, 抱歉.

年終總結(jié)也都沒有時(shí)間寫, 抽空寫這么一篇, 提前祝大家新年快樂, 過年回家路上平安順利.

前情提要

上集講到, 小光統(tǒng)一了各個(gè)分店的制作熱干面的流程, 并且引入模板方法在不改變熱干面的制作流程基礎(chǔ)上可以定制其中某些步驟. 通過這些措施, 小光熱干面的品牌性也是更加深入人心, 生意紅紅火火.

此時(shí)的小光, 有了更多的時(shí)間去思考公司的前程, 他認(rèn)為, 一個(gè)良好的有序的組織架構(gòu)是公司發(fā)展的必要點(diǎn). 而此時(shí), 小光也有覺得是時(shí)候梳理下公司的組織架構(gòu)了.

所有示例源碼已經(jīng)上傳到Github, 戳這里

組織架構(gòu)

小光參考了當(dāng)前很多公司的一些架構(gòu)方式, 根據(jù)分店, 職責(zé)簡單梳理了下目前小光熱干面的架構(gòu):


整個(gè)就是一個(gè)樹形結(jié)構(gòu).

  • 小光熱干面總部下面管理著各個(gè)分店, 也有其自己的部門.
  • 各個(gè)分店也有著自己的部門.

設(shè)計(jì)一套系統(tǒng)來表達(dá)這個(gè)組織架構(gòu)

梳理完組織關(guān)系后, 小光覺得有必要設(shè)計(jì)一套系統(tǒng)來管理這個(gè)關(guān)系圖, 以便后續(xù)能方便的查看和管理這個(gè)架構(gòu), 并能很清晰地講解給新員工.

簡單的開始

一開始, 小光并沒有想太多, 按照不同的層級(jí), 分別創(chuàng)建了總公司, 分店, 部門三個(gè)類:

// 部門
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);
        }
    }
}

利用這些層次的類來組成小光的組織架構(gòu):

public class XiaoGuang {

    public static void main(String[] args) {

        HeadOffice headOffice = new HeadOffice("小光熱干面");

        Department financeDept = new Department("財(cái)務(wù)部");
        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();
    }
}

結(jié)果如下, 達(dá)到要求:

總公司:小光熱干面
 - 分公司:光谷分店 - 部門:財(cái)務(wù)部 - 部門:策劃部
 - 分公司:花山分店 - 部門:財(cái)務(wù)部 - 部門:策劃部
 - 部門:財(cái)務(wù)部
 - 部門:策劃部

小光的思考

看著這新鮮出爐的架構(gòu)程序, 小光總覺得哪兒不對(duì)勁兒. 畢竟小光是歷經(jīng)了北上廣各種類型公司的人才啊, 回想起上班敲代碼的日子, 小光想起了哪兒不妥了. 公司總會(huì)發(fā)展, 發(fā)展過程中總會(huì)有一些戰(zhàn)略調(diào)整, 從而導(dǎo)致公司部門的各種變化.

目前小光設(shè)計(jì)的組織架構(gòu)是三層架構(gòu), 但是隨著公司的發(fā)展壯大, 很有可能層級(jí)會(huì)變得更多. 比如說, 總部的采購部壯大了, 可能會(huì)增加下一級(jí)的食材采購部和設(shè)備采購部. 甚至可能現(xiàn)在的層級(jí)還會(huì)隨著公司的戰(zhàn)略調(diào)整而升降. 例如, 如果分店開到別的城市了, 可能會(huì)在總部和分店之間插入一層"子公司"來分別管理各地的分店. 如下:


那么就出現(xiàn)了一個(gè)我們一直在強(qiáng)調(diào)的問題: 有些東西可能會(huì)一直有變化, 而我們從產(chǎn)品角度肯定會(huì)想要擁抱變化, 然而代碼層面上我們又不想修改代碼(修改原有代碼意味著還有對(duì)原有邏輯負(fù)責(zé)).

那應(yīng)該怎么辦呢? 有沒有更好的方式來表達(dá)這種樹形的組織架構(gòu)關(guān)系呢? 以便能夠很容易地?cái)U(kuò)展層次呢?

小光又回想起了自己的碼農(nóng)時(shí)代, 回想當(dāng)年這種問題的解決方案:

既然是因?yàn)樽兓? 擴(kuò)展而引起的問題, 我們最重要是要先找出系統(tǒng)中可變不可變的部分, 封裝不可變(使其修改關(guān)閉), 擁抱可變(使其擴(kuò)展開放).

小光的解決之道

那么具體到這個(gè)組織系統(tǒng)架構(gòu)的問題, 又該怎么做呢?

小光可不想每增加一個(gè)層級(jí)都要重新為其增加一個(gè)類, 然后改變原有系統(tǒng). 特別是有些情況下, 曾加的類(子公司)中可能會(huì)包含分店和自己的部門. 隨著類別的增加, 每次增加一個(gè)層級(jí)將會(huì)越來越難.

小光想到著, 突然想到:

每個(gè)部門/分店/子公司乃至總公司不都是部門的集合嗎?
部門可能有下屬部門, 可能沒有
分店下有部門
子公司下有分店, 可能還有自己的部門
總公司下有子公司, 分店, 自己的部門

所以說, 所有實(shí)體(總公司/子公司/分店/部門)實(shí)際上都是由部門組成的. 這些實(shí)體也都可以看著是一個(gè)部門.

想到做到:

首先定義出基礎(chǔ)的部門:

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這一個(gè)類別怎么搭建組織:

public class XiaoGuang {

    public static void main(String[] args) {

        Department financeDept = new Department("財(cái)務(wù)部");
        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);
    }
}

輸出如下

小光熱干面
 - 武漢子公司
    - 光谷分店
        - 財(cái)務(wù)部
        - 策劃部
    - 花山分店
        - 財(cái)務(wù)部
        - 策劃部
 - 長沙子公司
 - 財(cái)務(wù)部
 - 策劃部

輸出稍有調(diào)整, 以顯示直觀的層級(jí). 大家可以自行修改下代碼, 來給department加入level屬性, 以便輸出更完美的結(jié)構(gòu).

到此, 我們算是解決了組織架構(gòu)的問題了, 以后不管是增加了什么層級(jí), 我們都只需要使用Department來表示即可, 而無需增加一個(gè)類了.

故事之后

照例, 我們來縷縷小光設(shè)計(jì)的這套系統(tǒng)的"類關(guān)系":


結(jié)構(gòu)相當(dāng)簡單, 實(shí)際上就是一個(gè)類, 其中關(guān)鍵的是: 這個(gè)類中有一個(gè)list屬性(subDepartments)包含的是一組該類. 有點(diǎn)遞歸的感覺.

這個(gè)就是我們今天想說的 --- 組合模式

組合模式
又叫部分整體模式玄窝,通過組合的方式, 創(chuàng)建一個(gè)包含了一組自己的對(duì)象組(List<Department>)的類(Department). 從而達(dá)成了用一個(gè)類來遞歸地表示一個(gè)整體.

組合模式通常用來解決樹形結(jié)構(gòu)的表達(dá)問題, 例如本例中的組織結(jié)構(gòu).
所謂組合的方式, 就是創(chuàng)建一個(gè)包含了一組自己的對(duì)象組的類


注: 我們這里實(shí)現(xiàn)的相對(duì)簡單, 旨在說明模式的形式.
實(shí)際場景中, Department可能是一個(gè)抽象的, 例如有一個(gè)抽象方法來執(zhí)行該部門的職責(zé), 有不同的具體部門實(shí)現(xiàn)來實(shí)現(xiàn)其職責(zé). 從而有不同的"Department實(shí)現(xiàn)"來組合另一個(gè)大的Department節(jié)點(diǎn).

擴(kuò)展閱讀一

前面說到, 組合模式通常用來處理樹形結(jié)構(gòu)的表達(dá)問題. 而我們的用戶界面實(shí)現(xiàn)通常就是一個(gè)UI元素的節(jié)點(diǎn)樹. 例如HTML中的div中可能有button, 還會(huì)有其他div層級(jí), 依次往下; Java SE中的界面實(shí)現(xiàn)AWT和Swing包也到處是組合模式的體現(xiàn); Android中的View體系, View和ViewGroup, Layout層級(jí)樹也都是組合模式的體現(xiàn).

在此我們以Android的View體系為例, 簡單描述下.
眾所周知, Android的界面實(shí)際上就是一顆大樹, Hierarchy Viewer中展示的就是一個(gè)樹形結(jié)構(gòu). 我們來看下Android是怎么利用組合模式實(shí)現(xiàn)的.

如下:

  1. ViewGroup就是相當(dāng)于例子中的Department, 這里面比我們的例子復(fù)雜的是, ViewGroup是擴(kuò)展自View的, View實(shí)際上我們可以理解為是葉子節(jié)點(diǎn), 也就是最小的組成單元了, 不再有以下的層級(jí)了.
  2. ViewGroup中包含了一組View對(duì)象, 因?yàn)閂iewGroup是View的子類, 故而我們也可以說ViewGroup中包含了一組ViewGroup和/或View. 進(jìn)入形成了我們之前說的遞歸, 生成一個(gè)樹形結(jié)構(gòu).

關(guān)于View的體系, 在此不細(xì)述了.


搭建好彈性可擴(kuò)展的組織架構(gòu)體系, 小光又開始將眼光轉(zhuǎn)移到市場, 轉(zhuǎn)移到業(yè)務(wù)了, 準(zhǔn)備著新年大展拳腳~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尚镰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌构韵,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡捎拯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門盲厌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來署照,“玉大人,你說我怎么就攤上這事吗浩〗ㄜ剑” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵懂扼,是天一觀的道長禁荸。 經(jīng)常有香客問我,道長阀湿,這世上最難降的妖魔是什么屡限? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮炕倘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翰撑。我一直安慰自己罩旋,他們只是感情好啊央,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涨醋,像睡著了一般瓜饥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浴骂,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天乓土,我揣著相機(jī)與錄音,去河邊找鬼溯警。 笑死趣苏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梯轻。 我是一名探鬼主播食磕,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喳挑!你這毒婦竟也來了彬伦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤伊诵,失蹤者是張志新(化名)和其女友劉穎单绑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曹宴,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搂橙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浙炼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片份氧。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖弯屈,靈堂內(nèi)的尸體忽然破棺而出蜗帜,到底是詐尸還是另有隱情,我是刑警寧澤资厉,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布厅缺,位于F島的核電站,受9級(jí)特大地震影響宴偿,放射性物質(zhì)發(fā)生泄漏湘捎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一窄刘、第九天 我趴在偏房一處隱蔽的房頂上張望窥妇。 院中可真熱鬧,春花似錦娩践、人聲如沸活翩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽材泄。三九已至沮焕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拉宗,已是汗流浹背峦树。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旦事,地道東北人魁巩。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像族檬,于是被迫代替她去往敵國和親歪赢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容