1. 組合模式簡(jiǎn)介
組合模式(Composite Pattern)是結(jié)構(gòu)性設(shè)計(jì)模式,又叫“部分-整體”模式态辛,主要用于樹形結(jié)構(gòu)的處理麸澜。父節(jié)點(diǎn)是整體,子節(jié)點(diǎn)是父節(jié)點(diǎn)的部分奏黑,它們具有相似的行為炊邦。
組合模式的角色一共有三種编矾。
Leaf(葉節(jié)點(diǎn)角色): 葉子節(jié)點(diǎn),即沒(méi)有字節(jié)點(diǎn)的節(jié)點(diǎn)馁害,本模式中的“部分”角色洽沟,例如文件系統(tǒng)中文件。
Composite(枝節(jié)點(diǎn)角色):枝節(jié)點(diǎn)蜗细,即本模式中的“整體”角色裆操,它包含子節(jié)點(diǎn),字節(jié)點(diǎn)既可以是枝節(jié)點(diǎn)炉媒,也可以是葉節(jié)點(diǎn)踪区;例如文件系統(tǒng)中的文件夾。
Component(抽象組件角色): 是組合模式中Composite和Leaf共同的父接口(抽象類)吊骤,在此接口中聲明所有子類的共有的方法缎岗。
2. 組合模式舉例
公司有部門和員工,可以形成一個(gè)樹形結(jié)構(gòu)白粉,如果有一份通知要下發(fā)個(gè)全部的部門传泊,或者某個(gè)事業(yè)部,需要選中對(duì)應(yīng)的節(jié)點(diǎn)鸭巴,即可完成對(duì)該節(jié)點(diǎn)所有子節(jié)點(diǎn)的通知眷细。
序號(hào) | 類名 | 角色 | 說(shuō)明 |
---|---|---|---|
1 | Node | Component | 抽象組件角色,抽象節(jié)點(diǎn) |
2 | Staff | Leaf | 葉節(jié)點(diǎn)角色鹃祖,員工 |
3 | OrgNode | Composite | 枝節(jié)點(diǎn)角色溪椎,部門(公司、事業(yè)部) |
4 | CompisteMain | 客戶端 | 演示調(diào)用恬口,通知發(fā)布 |
1. Node類
// 抽象組件校读,抽象的組織結(jié)構(gòu)節(jié)點(diǎn)
public interface Node {
// 增加子節(jié)點(diǎn)
void add(Node node);
// 移除子節(jié)點(diǎn)
void remove(Node node);
// 獲取第i個(gè)子節(jié)點(diǎn)
Node get(int i);
// 發(fā)布通知
void inform(String information);
}
2. Staff類
// 葉節(jié)沒(méi)有子節(jié)點(diǎn),因此它實(shí)現(xiàn)的add祖能、remove等方法拋出異常歉秫。
public class Staff implements Node {
private String name;
public Staff(String name) {
this.name = name;
}
@Override
public void add(Node node) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Node node) {
throw new UnsupportedOperationException();
}
@Override
public Node get(int i) {
throw new UnsupportedOperationException();
}
@Override
public void inform(String information) {
System.out.println("員工 [" + name + "] 收到通知:" + information);
}
}
3. OrgNode
// 枝節(jié)點(diǎn)角色
public class OrgNode implements Node {
private String name;
private List<Node> nodeList = new ArrayList<>();
public OrgNode(String name) {
this.name = name;
}
@Override
public void add(Node node) {
nodeList.add(node);
}
@Override
public void remove(Node node) {
nodeList.remove(node);
}
@Override
public Node get(int i) {
Node node = null;
if (i >= 0 && i < nodeList.size()) {
node = nodeList.get(i);
}
return node;
}
// 遞歸調(diào)用
@Override
public void inform(String information) {
System.out.println("機(jī)構(gòu) [" + name + "] 收到通知:" + information);
for (Node node : nodeList) {
node.inform(information);
}
}
}
4. CompositeMain
public class CompisteMain {
public static void main(String[] args) {
Node com = new OrgNode("公司");
Node market = new OrgNode("市場(chǎng)部");
Node rd = new OrgNode("研發(fā)部");
Node ceo = new Staff("ceo 王");
com.add(market);
com.add(rd);
com.add(ceo);
Node steve = new Staff("史蒂夫");
market.add(steve);
Node james = new Staff("詹姆斯");
Node vince = new Staff("文斯");
rd.add(james);
rd.add(vince);
String infomation = " 1 + 1 = 2 ";
com.inform(infomation);
}
}
輸出結(jié)果:
機(jī)構(gòu) [公司] 收到通知: 1 + 1 = 2
機(jī)構(gòu) [市場(chǎng)部] 收到通知: 1 + 1 = 2
員工 [史蒂夫] 收到通知: 1 + 1 = 2
機(jī)構(gòu) [研發(fā)部] 收到通知: 1 + 1 = 2
員工 [詹姆斯] 收到通知: 1 + 1 = 2
員工 [文斯] 收到通知: 1 + 1 = 2
員工 [ceo 王] 收到通知: 1 + 1 = 2
3. 組合模式總結(jié)
組合模式非常適合樹形結(jié)構(gòu)的處理,當(dāng)要求父節(jié)點(diǎn)和子節(jié)點(diǎn)具有相同的功能的時(shí)候养铸。
但Leaf中實(shí)現(xiàn)了不必要的方法雁芙,客戶端不知道操作的節(jié)點(diǎn)是Leaf還是Composite,可能導(dǎo)致不安全揭厚。
如果抽象組件(例如本例的Node)中僅定義inform方法却特,而把a(bǔ)dd、remove筛圆、get等放入Composite類中裂明,那么可以避免上述不安全問(wèn)題;但客戶端需要就要區(qū)分Leaf和Composite了。
(完)