组合模式【结构型模式】

一、引入组合模式

设计一个大学>学院>专业的结构代码,可以做到输出大学、学院、专业的信息。

  • 一个大学里面有多个学院
  • 一个学院里面有多个专业

思路

在这里插入图片描述

我们很容易就想到这种组合的方式,去设计我们的代码。完全没有问题,可以很好的去实现我们的功能。

但是后面如果变动的时候就麻烦了。 假如我们要让大学直接去使用专业呢?



二、组合模式

组合模式(Composite Pattern) 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户可以使用一致的方法操作单个对象和组合对象。

在这里插入图片描述

组合模式有三个角色:

组合部件(Component):它可以是抽象类、接口、类。它里面定义了基本的属性和方法。
合成部件(Composite):还有自己的子节点,比如这里的大学、学院
叶子(Leaf):在组合中表示子节点对象,比如这里的专业。

代码演示

Component

import lombok.Data;
@Data
public abstract class Component {

     protected String name;

     protected void add(Component component){
         throw new UnsupportedOperationException();
     }

     protected void remove(Component component){
         throw new UnsupportedOperationException();
     }

     abstract void print();
}

注:
    1、比如我们上面的大学里面有学院,那么它就需要添加一个学院(add())和删除一个学院(remove())。但是我们的专业(也就是叶子节点),它不需要这个添加和删除方法,所以我们进行一个默认实现,里面抛出这个异常表示不支持此方法。
    2、这里为什么不用接口呢?(JDK8之后允许接口有默认实现),因为接口里面不允许定义非常量的变量。


University

import java.util.ArrayList;
import java.util.List;

public class University extends Component {

    private List<Component> lists = new ArrayList<>();

    public University(String name){
        super();
        setName(name);
    }

    @Override
    public void add(Component component) {
        lists.add(component);
    }

    @Override
    public void remove(Component component) {
        lists.remove(component);
    }

    @Override
    public void print() {
        System.out.println("----------"+getName()+"----------");
        for (Component c : lists){
            c.print();
        }
    }
}

College

import java.util.ArrayList;
import java.util.List;

public class College extends Component {

    private List<Component> lists = new ArrayList<>();

    public College(String name){
        super();
        setName(name);
    }

    @Override
    public void add(Component component) {
        lists.add(component);
    }

    @Override
    public void remove(Component component) {
        lists.remove(component);
    }

    @Override
    public void print() {
        System.out.println("----------"+getName()+"----------");
        for (Component c : lists){
            c.print();
        }
    }
}


Major

public class Major extends Component {

    public Major(String name){
        super();
        setName(name);
    }
    
    @Override
    void print() {
        System.out.println(getName());
    }
}

测试

public class Main {
    public static void main(String[] args) {
        // 创建学校
        University university = new University("沙雕大学");

        // 创建学院
        College college_1 = new College("计算机与科学学院");
        College college_2 = new College("人文艺术学院");

        // 大学与学院关联
        university.add(college_1);
        university.add(college_2);

        // 创建专业
        Major major_1 = new Major("软件工程");
        Major major_2 = new Major("网络工程");
        Major major_3 = new Major("音乐与舞蹈");
        Major major_4 = new Major("表演与艺术");

        // 学院与专业关联
        college_1.add(major_1);
        college_1.add(major_2);
        college_2.add(major_3);
        college_2.add(major_4);

        // 测试
        // 打印大学
        university.print();
        // ----------沙雕大学----------
        // ----------计算机与科学学院----------
        // 软件工程
        // 网络工程
        // ----------人文艺术学院----------
        // 音乐与舞蹈
        // 表演与艺术

        // 打印学院
        college_1.print();
        // ----------计算机与科学学院----------
        // 软件工程
        // 网络工程

        // 打印专业
        major_1.print();
        // 软件工程
    }
}

总结

  • 客户端只需要面对对象即可,不需要考虑整体部分和叶子节点的问题。
  • 具有较强的扩展性。当我们需要更改组合对象时,我们只需要调整内部的层次关系即可。
  • 需要遍历组织机构,或者处理的对象具有树形结构时,非常适合使用组合模式。
  • 如果节点和叶子有很多差异的话,比如很多属性、或方法不一样,就不适合使用组合模式了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章