请相信自己,请再次相信自己,请一定要相信自己
上一章简单介绍了装饰者模式(十一), 如果没有看过, 请观看上一章
一. 组合模式
引用 菜鸟教程里面的 组合 模式介绍: https://www.runoob.com/design-pattern/composite-pattern.html
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,
它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
一.一 介绍
意图: 将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决: 它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决: 树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码 树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
应用实例 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作数也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点 1、高层模块调用简单。 2、节点自由增加。
缺点 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景 部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项 定义时为具体类。
组成角色 | 具体 | 关系 | 作用 |
---|---|---|---|
Component | OrgComponent | 用于访问和管理 Component 子部件 | 用于访问和管理 Component 子部件 |
Leaf | ZhuanYe | 叶子节点,没有子节点 | 叶子节点,没有子节点 |
Composite | DaXue, XueYuan | 非叶子节点,用于存储子部件 | 非叶子节点,用于存储子部件 |
二. 组合模式实例
-
定义一个 抽象类, 填入基本的属性和方法
-
针对抽象类进行实现, 有叶子节点实现 和 非叶子节点实现
叶子节点实现的话, 没有集合的操作
非叶子节点实现的话, 是有集合引用的, 需要针对集合中的每一个操作进行处理。
二.一 定义子元素
@Data
public abstract class OrgComponent {
private String name;
private String desc;
public OrgComponent (String name, String desc) {
this.name = name;
this.desc = desc;
}
public void add (OrgComponent orgComponent) {
throw new UnsupportedOperationException();
}
public void remove(OrgComponent orgComponent) {
throw new UnsupportedOperationException();
}
public OrgComponent getChild(int i) {return null;}
public abstract void print();
}
二.二 叶子节点
@Slf4j
public class ZhuanYe extends OrgComponent{
public ZhuanYe(String name, String desc) {
super(name, desc);
}
@Override
public void print() {
log.info(">>>>>>>>>>>>>>>>>>>>>>{}",getName());
}
}
二.三 非叶子节点
二.三.一 大学
@Slf4j
public class DaXue extends OrgComponent{
private List<OrgComponent> children = new ArrayList<>();
public DaXue(String name, String desc) {
super(name, desc);
}
@Override
public void add(OrgComponent orgComponent) {
children.add(orgComponent);
}
@Override
public void remove(OrgComponent orgComponent) {
Iterator<OrgComponent> iterator = children.iterator();
while(iterator.hasNext()) {
OrgComponent next = iterator.next();
if (next.getName().equals(orgComponent.getName())) {
iterator.remove();
}
}
}
@Override
public OrgComponent getChild(int i) {
if (children.size() > i) {
return children.get(i);
}else {
return null;
}
}
@Override
public void print() {
if (!CollectionUtil.isEmpty(children)){
log.info(">{}",getName());
for (OrgComponent orgComponent : children) {
orgComponent.print();
}
}
}
}
二.三.二 学院
@Slf4j
public class XueYuan extends OrgComponent{
private List<OrgComponent> children = new ArrayList<>();
public XueYuan(String name, String desc) {
super(name, desc);
}
@Override
public void add(OrgComponent orgComponent) {
children.add(orgComponent);
}
@Override
public void remove(OrgComponent orgComponent) {
Iterator<OrgComponent> iterator = children.iterator();
while(iterator.hasNext()) {
OrgComponent next = iterator.next();
if (next.getName().equals(orgComponent.getName())) {
iterator.remove();
}
}
}
@Override
public OrgComponent getChild(int i) {
if (children.size() > i) {
return children.get(i);
}else {
return null;
}
}
@Override
public void print() {
if (!CollectionUtil.isEmpty(children)){
log.info(">>>>>>>>>>>{}",getName());
for (OrgComponent orgComponent : children) {
orgComponent.print();
}
}
}
}
二.四 测试方法
@Test
public void oneTest() {
OrgComponent daXue = new DaXue("大学","大学1");
OrgComponent xueYuan1 = new XueYuan("学院1","学院1");
OrgComponent xueYuan2 = new XueYuan("学院2","学院2");
daXue.add(xueYuan1);
daXue.add(xueYuan2);
// 添加专业
OrgComponent zhuanYe1 = new ZhuanYe("专业1","专业1");
OrgComponent zhuanYe2 = new ZhuanYe("专业2","专业2");
OrgComponent zhuanYe3 = new ZhuanYe("专业3","专业3");
OrgComponent zhuanYe4 = new ZhuanYe("专业4","专业4");
xueYuan1.add(zhuanYe1);
xueYuan1.add(zhuanYe2);
xueYuan2.add(zhuanYe3);
xueYuan2.add(zhuanYe4);
log.info(">>>>> 移除之前 大学打印: ");
// 进行打印
daXue.print();
log.info(">>>>> 移除之前 学院打印: ");
xueYuan1.print();
xueYuan1.remove( zhuanYe1);
log.info(">>>>> 移除之后打印: ");
daXue.print();
xueYuan1.print();
}
需要遍历组织机构,或者处理的对象具有树形结构时, 非常适合使用组合模式
要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式
本章节的代码放置在 github 上:
https://github.com/yuejianli/DesignPattern/tree/develop/Composite
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!