java 设计模式之组合模式(九)

人这一辈子,要做一个平静的人,做一个善良的人,做一个微笑挂在嘴边,快乐放在心上的人。有时候能放下自己的脾气向你的坏脾气低头的人,并不是因为怕你,而是比你更懂得珍惜。

设计模式学习,近期我会把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):在这里插入图片描述
可以看到,及时是加了教导主任类,让教导主任去管理老师,也没有去处理很多的代码,而且写起来非常方便快捷.最终要的是满足开闭原则(对扩展开放,对修改关闭)!

完整代码

去设计模式/设计原则主页

原创不易,您的点赞就是对我最大的支持,点个赞支持一下吧~

猜你喜欢

转载自blog.csdn.net/weixin_44819566/article/details/112469634