1、 合成模式
概述1.1、 核心组件1.2、 优点缺陷2、 Java
实现1)组件接口规范2)组件实现3)实现测试4)测试结果3、 Python
实现4、 Go
实现1) 合成/组合模式:抽象接口2) Leaf
组件实现3) Composite
实现4) 关于GO
1、 合成模式
概述
合成模式[Composite
]也称为部分-整体模式[Part-Whole
]、组合模式,合成模式中将对象组织到树形结构中,针对同一种对象描述整体和部分的关系,合成模式下可以将简单对象和组合对象同等对待。
提到合成模式,总会想起这样一个故事 从前有座山,山里有座庙,庙里有个老和尚,庙里有个小和尚,老和尚给小和尚讲故事,讲的什么故事呢?从前有座山…
。
在项目开发的某些情况下需要类似树形结构的对象架构,如项目中常规的组织结构关系,权限管理关系、文件目录结构等等,都需要通过类似树形结构的软件架构进行定义,合成模式就是针对这样的结构的一种通用解决方案。
1.1、 核心组件
合成模式中核心主要包含两部分组件,包含下级节点的组件和不包含下级节点的组件,如果形容成一个树形结构的话我们称为 树枝节点
和 树叶节点
。
合成模式中,根据树枝节点和树叶节点两种节点的是否一致性,区分为透明形式
和安全形式
,不论哪种处理形式都是通过组件的嵌套组合完成部分-整体的关联关系,通过这样的关联关系表达树形结构。
1.2、 优点缺陷
优点:
高层模块调用简单, 节点自由增加。
缺陷:
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则,同时不容易限制组合中的组件。
2、 Java
实现
1)组件接口规范
package com.damu;
import com.sun.org.apache.xpath.internal.operations.String;
import java.util.List;
/**
* <p>项目文档: 合成模式 接口规范 </p>
*
* @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
* @version V1.0
*/
public interface IComponent {
/**
* 增加节点
* @param component 要增加的节点对象
*/
IComponent add(IComponent component);
/**
* 删除节点
* @param component 要删除的节点对象
*/
IComponent remove(IComponent component);
/**
* 判断是否包含子节点
* @return 返回判断结果
*/
Boolean hasChildComponent();
/**
* 获取自身节点
* @return 返回当前节点
*/
IComponent getComponentSelf();
/**
* 获取所有子节点
* @return 所有子节点
*/
List<IComponent> getComponentsChild();
/**
* 遍历节点信息
*/
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());
// 获取所有子节点
for (IComponent childComponent : component.getComponentsChild()) {
IComponent.lookUpComponent(childComponent, depth + 2);
}
return;
}
System.out.println(sb + "Leaf: " + ((Composite)component).getData());
}
}
2)组件实现
package com.damu;
import java.util.List;
import java.util.Vector;
/**
* <p>项目文档: 树枝节点 </p>
*
* @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
* @version V1.0
*/
public class Composite implements IComponent {
// 子节点集合
private Vector<IComponent> vector = new Vector<IComponent>();
// 当前节点数据
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)实现测试
package com.damu;
/**
* <p>项目文档: 合成模式 透明状态 测试代码</p>
*
* @author <a href="https://github.com/laomu/laomu.github.io">大牧</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(" ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~");
// 组织关系
Composite ali = new Composite("阿里总部");
Composite hz = new Composite("杭州服务部");
Composite sh = new Composite("上海营销部");
Composite bj = new Composite("北京技术部");
Composite hz01 = new Composite("电商服务部");
Composite hz02 = new Composite("营销服务部");
Composite sh01 = new Composite("营销策划部");
Composite sh02 = new Composite("营销推广部");
Composite bj01 = new Composite("秒杀技术组");
Composite bj02 = new Composite("抢购技术组");
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)测试结果
合成模式,也称为组合模式,通过类型自身的组合关系表达了部分-整体的逻辑结构,上述代码运行结果:
Composite: 开始讲故事...
----Leaf: 从前有座山
----Composite: 山里有座庙
--------Leaf: 庙里有个老和尚
--------Leaf: 庙里有个小和尚
~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~
Composite: 阿里总部
----Composite: 杭州服务部
--------Leaf: 电商服务部
--------Leaf: 营销服务部
----Composite: 上海营销部
--------Leaf: 营销策划部
--------Leaf: 营销推广部
----Composite: 北京技术部
--------Leaf: 秒杀技术组
--------Leaf: 抢购技术组
--------Leaf: 推荐平台组
3、 Python
实现
"""
设计模式——组合模式
组合模式(Composite Pattern):将对象组合成成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性.
"""
# 抽象一个组织类
class Component(object):
def __init__(self, name):
self.name = name
def add(self,comp):
raise NotImplementedError("该方法必须在子类中实现")
def remove(self,comp):
raise NotImplementedError("该方法必须在子类中实现")
def lookup(self, depth):
raise NotImplementedError("该方法必须在子类中实现")
# 叶子节点
class Leaf(Component):
def add(self,comp):
print('不能添加下级节点')
def remove(self,comp):
print('不能删除下级节点')
def lookup(self, depth):
strtemp = ''
for i in range(depth):
strtemp += strtemp + '-'
print strtemp+self.name
# 枝节点
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
实现
1) 合成/组合模式:抽象接口
type IComponent interface {
Name() string
Description() string
Price() float32
LookUp()
Add(IComponent)
Remove(int)
Child(int) IComponent
}
2) Leaf
组件实现
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("树叶节点,不包含该方法")
}
func (m *Leaf) Remove(int) {
panic("树叶节点,不包含该方法")
}
func (m *Leaf) Child(int) IComponent {
panic("树叶节点,不包含该方法")
}
3) Composite
实现
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) 关于GO
其实更多时候Go
语言的定位不是如此繁复的业务处理逻辑,而是数据结构的直观描述,类似合成设计模式这样的结构模式,在Go
语言中应该直接通过组合的方式将不同的数据进行规范定义即可,没有必要为赋新词强说愁
,没有那么多接口没有那么多继承,只是简单的通过不同复杂数据的组合方式完成即可。这一点上,上述代码就显得非常不友好了。