1斟叼、 合成模式
概述1.1、 核心組件1.2煤蹭、 優(yōu)點(diǎn)缺陷2、 Java
實(shí)現(xiàn)1)組件接口規(guī)范2)組件實(shí)現(xiàn)3)實(shí)現(xiàn)測試4)測試結(jié)果3川梅、 Python
實(shí)現(xiàn)4疯兼、 Go
實(shí)現(xiàn)1) 合成/組合模式:抽象接口2) Leaf
組件實(shí)現(xiàn)3) Composite
實(shí)現(xiàn)4) 關(guān)于GO
1、 合成模式
概述
合成模式[Composite
]也稱為部分-整體模式[Part-Whole
]贫途、組合模式吧彪,合成模式中將對象組織到樹形結(jié)構(gòu)中,針對同一種對象描述整體和部分的關(guān)系丢早,合成模式下可以將簡單對象和組合對象同等對待姨裸。
提到合成模式秧倾,總會想起這樣一個故事 從前有座山,山里有座廟傀缩,廟里有個老和尚那先,廟里有個小和尚,老和尚給小和尚講故事赡艰,講的什么故事呢售淡?從前有座山…
。
在項(xiàng)目開發(fā)的某些情況下需要類似樹形結(jié)構(gòu)的對象架構(gòu)揖闸,如項(xiàng)目中常規(guī)的組織結(jié)構(gòu)關(guān)系,權(quán)限管理關(guān)系料身、文件目錄結(jié)構(gòu)等等汤纸,都需要通過類似樹形結(jié)構(gòu)的軟件架構(gòu)進(jìn)行定義,合成模式就是針對這樣的結(jié)構(gòu)的一種通用解決方案芹血。
1.1贮泞、 核心組件
合成模式中核心主要包含兩部分組件,包含下級節(jié)點(diǎn)的組件和不包含下級節(jié)點(diǎn)的組件幔烛,如果形容成一個樹形結(jié)構(gòu)的話我們稱為 樹枝節(jié)點(diǎn)
和 樹葉節(jié)點(diǎn)
啃擦。
合成模式中,根據(jù)樹枝節(jié)點(diǎn)和樹葉節(jié)點(diǎn)兩種節(jié)點(diǎn)的是否一致性说贝,區(qū)分為透明形式
和安全形式
议惰,不論哪種處理形式都是通過組件的嵌套組合完成部分-整體的關(guān)聯(lián)關(guān)系慎颗,通過這樣的關(guān)聯(lián)關(guān)系表達(dá)樹形結(jié)構(gòu)乡恕。
1.2、 優(yōu)點(diǎn)缺陷
優(yōu)點(diǎn):
高層模塊調(diào)用簡單俯萎, 節(jié)點(diǎn)自由增加傲宜。
缺陷:
在使用組合模式時,其葉子和樹枝的聲明都是實(shí)現(xiàn)類夫啊,而不是接口函卒,違反了依賴倒置原則,同時不容易限制組合中的組件撇眯。
2报嵌、 Java
實(shí)現(xiàn)
1)組件接口規(guī)范
package com.damu;
import com.sun.org.apache.xpath.internal.operations.String;
import java.util.List;
/**
* <p>項(xiàng)目文檔: 合成模式 接口規(guī)范 </p>
*
* @author <a >大牧</a>
* @version V1.0
*/
public interface IComponent {
/**
* 增加節(jié)點(diǎn)
* @param component 要增加的節(jié)點(diǎn)對象
*/
IComponent add(IComponent component);
/**
* 刪除節(jié)點(diǎn)
* @param component 要刪除的節(jié)點(diǎn)對象
*/
IComponent remove(IComponent component);
/**
* 判斷是否包含子節(jié)點(diǎn)
* @return 返回判斷結(jié)果
*/
Boolean hasChildComponent();
/**
* 獲取自身節(jié)點(diǎn)
* @return 返回當(dāng)前節(jié)點(diǎn)
*/
IComponent getComponentSelf();
/**
* 獲取所有子節(jié)點(diǎn)
* @return 所有子節(jié)點(diǎn)
*/
List<IComponent> getComponentsChild();
/**
* 遍歷節(jié)點(diǎn)信息
*/
static void lookUpComponent(IComponent component, Integer depth) {
StringBuffer sb = new StringBuffer("");
for (int i = 0; i < depth; i++) {
sb.append("--");
}
if (component.hasChildComponent()) {
System.out.println(sb + "Composite: " + ((Composite)component).getData());
// 獲取所有子節(jié)點(diǎn)
for (IComponent childComponent : component.getComponentsChild()) {
IComponent.lookUpComponent(childComponent, depth + 2);
}
return;
}
System.out.println(sb + "Leaf: " + ((Composite)component).getData());
}
}
2)組件實(shí)現(xiàn)
package com.damu;
import java.util.List;
import java.util.Vector;
/**
* <p>項(xiàng)目文檔: 樹枝節(jié)點(diǎn) </p>
*
* @author <a >大牧</a>
* @version V1.0
*/
public class Composite implements IComponent {
// 子節(jié)點(diǎn)集合
private Vector<IComponent> vector = new Vector<IComponent>();
// 當(dāng)前節(jié)點(diǎn)數(shù)據(jù)
private String data;
public Composite(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public IComponent add(IComponent component) {
this.vector.add(component);
return this;
}
@Override
public IComponent remove(IComponent component) {
this.vector.remove(component);
return this;
}
@Override
public Boolean hasChildComponent() {
return this.vector.size() > 0;
}
@Override
public IComponent getComponentSelf() {
return this;
}
@Override
public List<IComponent> getComponentsChild() {
return this.vector;
}
}
3)實(shí)現(xiàn)測試
package com.damu;
/**
* <p>項(xiàng)目文檔: 合成模式 透明狀態(tài) 測試代碼</p>
*
* @author <a >大牧</a>
* @version V1.0
*/
public class CompositeMain {
public static void main(String[] args) {
Composite story = new Composite("開始講故事...");
Composite mount = new Composite("從前有座山");
Composite temple = new Composite("山里有座廟");
Composite buddhistMonk = new Composite("廟里有個老和尚");
Composite childBuddhistMonk = new Composite("廟里有個小和尚");
// 從前有座山...loop 1 -> n
IComponent thisStory = story.add(mount).add(temple.add(buddhistMonk).add(childBuddhistMonk));
// 遍歷查看
IComponent.lookUpComponent(thisStory, 0);
System.out.println(" ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~");
// 組織關(guān)系
Composite ali = new Composite("阿里總部");
Composite hz = new Composite("杭州服務(wù)部");
Composite sh = new Composite("上海營銷部");
Composite bj = new Composite("北京技術(shù)部");
Composite hz01 = new Composite("電商服務(wù)部");
Composite hz02 = new Composite("營銷服務(wù)部");
Composite sh01 = new Composite("營銷策劃部");
Composite sh02 = new Composite("營銷推廣部");
Composite bj01 = new Composite("秒殺技術(shù)組");
Composite bj02 = new Composite("搶購技術(shù)組");
Composite bj03 = new Composite("推薦平臺組");
ali.add(hz.add(hz01).add(hz02))
.add(sh.add(sh01).add(sh02))
.add(bj.add(bj01).add(bj02).add(bj03));
IComponent.lookUpComponent(ali, 0);
}
}
4)測試結(jié)果
合成模式,也稱為組合模式熊榛,通過類型自身的組合關(guān)系表達(dá)了部分-整體的邏輯結(jié)構(gòu)锚国,上述代碼運(yùn)行結(jié)果:
Composite: 開始講故事...
----Leaf: 從前有座山
----Composite: 山里有座廟
--------Leaf: 廟里有個老和尚
--------Leaf: 廟里有個小和尚
~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~
Composite: 阿里總部
----Composite: 杭州服務(wù)部
--------Leaf: 電商服務(wù)部
--------Leaf: 營銷服務(wù)部
----Composite: 上海營銷部
--------Leaf: 營銷策劃部
--------Leaf: 營銷推廣部
----Composite: 北京技術(shù)部
--------Leaf: 秒殺技術(shù)組
--------Leaf: 搶購技術(shù)組
--------Leaf: 推薦平臺組
3、 Python
實(shí)現(xiàn)
"""
設(shè)計(jì)模式——組合模式
組合模式(Composite Pattern):將對象組合成成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),組合模式使得用戶對單個對象和組合對象的使用具有一致性.
"""
# 抽象一個組織類
class Component(object):
def __init__(self, name):
self.name = name
def add(self,comp):
raise NotImplementedError("該方法必須在子類中實(shí)現(xiàn)")
def remove(self,comp):
raise NotImplementedError("該方法必須在子類中實(shí)現(xiàn)")
def lookup(self, depth):
raise NotImplementedError("該方法必須在子類中實(shí)現(xiàn)")
# 葉子節(jié)點(diǎn)
class Leaf(Component):
def add(self,comp):
print('不能添加下級節(jié)點(diǎn)')
def remove(self,comp):
print('不能刪除下級節(jié)點(diǎn)')
def lookup(self, depth):
strtemp = ''
for i in range(depth):
strtemp += strtemp + '-'
print strtemp+self.name
# 枝節(jié)點(diǎn)
class Composite(Component):
def __init__(self, name):
self.name = name
self.children = list()
def add(self,comp):
self.children.append(comp)
def remove(self,comp):
self.children.remove(comp)
def lookup(self, depth):
strtemp = ''
for i in range(depth):
strtemp += strtemp+'-'
print(strtemp + self.name)
for comp in self.children:
comp.display(depth + 2)
if __name__ == "__main__":
#生成樹根
root = Composite("root")
#根上長出2個葉子
root.add(Leaf('leaf A'))
root.add(Leaf('leaf B'))
#根上長出樹枝Composite X
comp = Composite("Composite X")
comp.add(Leaf('leaf XA'))
comp.add(Leaf('leaf XB'))
root.add(comp)
#根上長出樹枝Composite X
comp2 = Composite("Composite XY")
#Composite X長出2個葉子
comp2.add(Leaf('leaf XYA'))
comp2.add(Leaf('leaf XYB'))
root.add(comp2)
# 根上又長出2個葉子,C和D,D沒張昊,掉了
root.add(Leaf('Leaf C'))
leaf = Leaf("Leaf D")
root.add(leaf)
root.remove(leaf)
#展示組織
root.lookup(1)
4玄坦、 Go
實(shí)現(xiàn)
1) 合成/組合模式:抽象接口
type IComponent interface {
Name() string
Description() string
Price() float32
LookUp()
Add(IComponent)
Remove(int)
Child(int) IComponent
}
2) Leaf
組件實(shí)現(xiàn)
type Leaf struct {
name string
description string
price float32
}
func Leaf(name, description string, price float32) IComponent {
return &Leaf{
name: name,
description: description,
price: price,
}
}
func (m *Leaf) Name() string {
return m.name
}
func (m *Leaf) Description() string {
return m.description
}
func (m *Leaf) Price() float32 {
return m.price
}
func (m *Leaf) Lookup() {
fmt.Printf(" %s, ¥%.2f\n", m.name, m.price)
fmt.Printf(" -- %s\n", m.description)
}
func (m *Leaf) Add(IComponent) {
panic("樹葉節(jié)點(diǎn)血筑,不包含該方法")
}
func (m *Leaf) Remove(int) {
panic("樹葉節(jié)點(diǎn)绘沉,不包含該方法")
}
func (m *Leaf) Child(int) IComponent {
panic("樹葉節(jié)點(diǎn),不包含該方法")
}
3) Composite
實(shí)現(xiàn)
type Composite struct {
name string
description string
children []IComponent
}
func NewMenu(name, description string) IComponent {
return &Composite{
name: name,
description: description,
}
}
func (m *Composite) Name() string {
return m.name
}
func (m *Composite) Description() string {
return m.description
}
func (m *Composite) Price() (price float32) {
for _, v := range m.children {
price += v.Price()
}
return
}
func (m *Composite) Print() {
fmt.Printf("%s, %s, ¥%.2f\n", m.name, m.description, m.Price())
fmt.Println("------------------------")
for _, v := range m.children {
v.Print()
}
fmt.Println()
}
func (m *Composite) Add(c IComponent) {
m.children = append(m.children, c)
}
func (m *Composite) Remove(idx int) {
m.children = append(m.children[:idx], m.children[idx+1:]...)
}
func (m *Composite) Child(idx int) IComponent {
return m.children[idx]
}
4) 關(guān)于GO
其實(shí)更多時候Go
語言的定位不是如此繁復(fù)的業(yè)務(wù)處理邏輯豺总,而是數(shù)據(jù)結(jié)構(gòu)的直觀描述车伞,類似合成設(shè)計(jì)模式這樣的結(jié)構(gòu)模式,在Go
語言中應(yīng)該直接通過組合的方式將不同的數(shù)據(jù)進(jìn)行規(guī)范定義即可喻喳,沒有必要為賦新詞強(qiáng)說愁
另玖,沒有那么多接口沒有那么多繼承,只是簡單的通過不同復(fù)雜數(shù)據(jù)的組合方式完成即可表伦。這一點(diǎn)上日矫,上述代碼就顯得非常不友好了。