人这一辈子,要做一个平静的人,做一个善良的人,做一个微笑挂在嘴边,快乐放在心上的人。有时候能放下自己的脾气向你的坏脾气低头的人,并不是因为怕你,而是比你更懂得珍惜。
设计模式学习,近期我会把23中设计模式都写成博客,敬请期待~
—2021/1/11
定义
组合模式又称之为部分整体模式,将对象组合成树形结构以表示“部分-整体”的层次结构。
使用场景
- 需要遍历组织机构,或者处理对象具有树形结构时,适合使用组合模式
- 要求较高的抽象性,如果’节点’和’叶子’有很大差异不建议使用组合模式
常见误区
组合模式不是用的组合,而是用的聚合!
普通情况分析
假设现在有一所学校,学校管理老师,老师管理学生,如何要遍历所有老师以及学生呢?
很大多情况应该都是这样的:
UML类图(1.1)
:
学校管理老师,老师管理学生,弄成这样多继承的关系
多继承的缺点:
- 如果要对学生进行添加或者删除不便于操作
- 耦合性太高,
- 需要修改原有代码,违背了开闭原则(对扩展开放,对修改关闭)
组合模式分析
UML类图(1.2)
:
分析:
- 学生类继承自学校类,并且学校类聚合自学生类
- 老师类继承自学校类,并且学校类聚合自老师类
角色分析:
- Comonent:这里充当着学校类(用来规范实现方法)
- Leaf:叶子节点,这里指学生类,因为学生类是最底部的,没有子节点
- Composite:非叶子节点,非叶子节点可以有多个,这里指老师类,非叶子节点下必须要有子节点.
举例:
- 教导主任(非叶子节点)
- 班主任(非叶子节点)
- 任课老师(非叶子节点)
- 学生(叶子节点)
教导主任 > 班主任 > 任课老师 > 学生
就像一颗大树一样,最底层的就是叶子
优点:
- 具有较强的扩展性,当我们需要添加新的对象时,不用改变原来代码,遵守了开闭原则(对扩展开放,对修改关闭)
- 方便创建出复杂的层次结构,客户端不用理会细节.
代码实现:
School 学校类:
用来规范代码
public abstract class School {
//名字
private String name;
//年级
private String grade;
//添加
public void add(School school){
}
//删除
public void remove(School school){
}
//输出日志
abstract void print();
public School(String name, String grade) {
this.name = name;
this.grade = grade;
}
get...
set...
}
这里的add()remove()方法为什么不写成abstract(抽象)的呢?
因为叶子节点不需要实现,避免产生误导.
Teacher 老师类:
public class Teacher extends School {
List<School> mList = new ArrayList<>();
public Teacher(String name, String grade) {
super(name, grade);
}
@Override//输出日志
void print() {
Log.i("组合模式:", "========" + getName() + "========");
for (int i = 0; i < mList.size(); i++) {
mList.get(i).print();
}
}
@Override
public void add(School school) {
mList.add(school);
}
@Override
public void remove(School school) {
mList.remove(school);
}
}
Student学生类:
public class Student extends School {
public Student(String name, String grade) {
super(name, grade);
}
@Override
void print() {
Log.i("组合模式", "========== " + getName() + getGrade() + " ==========");
}
}
测试代码:
Log.i("组合模式,","======= 振华中学 ======");
Teacher t1 = new Teacher("语文老师","一年级");
Teacher t2 = new Teacher("数学老师","二年级");
Teacher t3 = new Teacher("英语老师","三年级");
Teacher t4 = new Teacher("体育老师","四年级");
t1.add(new Student("小王","一年级"));
t1.add(new Student("小张","一年级"));
t1.add(new Student("小李","一年级"));
t2.add(new Student("小王","二年级"));
t2.add(new Student("小张","二年级"));
t2.add(new Student("小李","二年级"));
t1.print();
t2.print();
t3.print();
t4.print();
Log图(2.1)
:
如何添加新的节点?比如教导主任管理班主任:
Instructor教导主任类:
public class Instructor extends School {
private List<School> mlist = new ArrayList<>();
public Instructor(String name, String grade) {
super(name, grade);
}
@Override
public void add(School school) {
mlist.add(school);
}
@Override
public void remove(School school) {
mlist.remove(school);
}
@Override
void print() {
Log.i("组合模式", "----- " + getName() + getGrade() + "------");
for (int i = 0; i < mlist.size(); i++) {
mlist.get(i).print();
}
}
}
测试代码:
Log.i("组合模式,","======= 振华中学 ======");
Teacher t1 = new Teacher("语文老师","一年级");
Teacher t2 = new Teacher("数学老师","二年级");
Teacher t3 = new Teacher("英语老师","三年级");
Teacher t4 = new Teacher("体育老师","四年级");
t1.add(new Student("小王","一年级"));
t1.add(new Student("小张","一年级"));
t1.add(new Student("小李","一年级"));
t2.add(new Student("小王","二年级"));
t2.add(new Student("小张","二年级"));
t2.add(new Student("小李","二年级"));
Instructor instructor1 = new Instructor("王教导主任", "");
instructor1.add(t1);
instructor1.add(t2);
Instructor instructor2 = new Instructor("张教导主任", "");
instructor2.add(t3);
instructor2.add(t4);
instructor1.print();
instructor2.print();
Log图(2.2)
:
可以看到,及时是加了教导主任类,让教导主任去管理老师,也没有去处理很多的代码,而且写起来非常方便快捷.最终要的是满足开闭原则(对扩展开放,对修改关闭)!
原创不易,您的点赞就是对我最大的支持,点个赞支持一下吧~