原本是周更的频率, 由于真实的"小光"真实地逃离了北京, 回了武汉, 回了老家, 处理了一些私人事务. 也就有快一个月时间没有更新了, 抱歉.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的体系, 在此不细述了.
搭建好弹性可扩展的组织架构体系, 小光又开始将眼光转移到市场, 转移到业务了, 准备着新年大展拳脚~