设计模式之组合模式

Posted ProChick

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之组合模式相关的知识,希望对你有一定的参考价值。

1.简要概述

  • 组合模式又叫做部分整体模式,它将对象组合成树形结构来表示“整体与部分”之间的层次关系。
  • 组合模式使得用户对单个对象和组合对象的访问具有了一致性,即允许用户以统一的方式处理单个对象和组合对象。
  • 组合模式为处理树形结构提供了完美的解决方案,描述了如何将容器和叶子进行递归组合,使得用户在使用时可以一致性的对待容器和叶子。

2.模式结构

👉通常由一个抽象组件接口( 负责定义所有实现类共有的方法接口 ),多个具体的叶子实现类( 在组合模式中,它表示叶子节点,没有子节点 ),多个具体的组合实现类( 负责管理组件对象,实现对象的相关操作 ),一个客户类( 负责调用抽象组件接口来对单独对象和组合对象进行统一处理 )共同组成。

3.实现代码

举例 💡 :假设我们现在要对学校这个组织进行管理,我们知道学校下面又可以分为多个院系,院系下面又分为多个专业,所以这可以理解为是一个树性结构(组织充当抽象组件、学校和院系充当组合对象、专业充当叶子对象)。那么如果我们想要输出整个学校的院系专业信息,那么就可以使用组合模式进行处理。

组织类(抽象组件Component)

public abstract class Organization{
    protected String name;
    
    public Organization(String name){
        this.name = name;
    }
    
    public void add(Organization organization){
        //默认实现
    }
    
    public void remove(Organization organization){
        //默认实现
    }
    
    public abstract void print();
}

学校类(组合对象Composite)

public class School extends Organization{
    
    private List<Organization> childs = new ArraryList<Organization>();
    
    public School(String name){
        super(name);
    }
    
    @Override
    public void add(Organization organization){
        child.add(organization);
    }
    
    @Override
    public void remove(Organization organization){
        child.remove(organization);
    }
    
    @Override
    public void print(){
        System.out.println("****************" + name + "****************")
            
        for (Organization organization : childs) {
            System.out.println(organization.print());
        }
    }
}

学院类(组合对象Composite)

public class Academy extends Organization{
    
    private List<Organization> childs = new ArraryList<Organization>();
    
    public Academy(String name){
        super(name);
    }
    
    @Override
    public void add(Organization organization){
        child.add(organization);
    }
    
    @Override
    public void remove(Organization organization){
        child.remove(organization);
    }
    
    @Override
    public void print(){
        System.out.println("----------------" + name + "----------------")
            
        for (Organization organization : childs) {
            System.out.println(organization.print());
        }
    }
}

专业类(叶子对象Leaf)

public class Speciality extends Organization{

    public Speciality(String name){
        super(name);
    }

    @Override
    public void print(){
        System.out.println(name);
    }
}

客户类

// 测试客户端
public class OrganizationClient{
    public static void main(String[] args) {
        // 创建一个学校对象
        Organization school = new School("北京大学");
        
        // 为学校添加两个学院
        Organization softwareAcademy = new Academy("软件学院");
        Organization infoAcademy = new Academy("信息工程学院");
        school.add(softwareAcademy);
        school.add(infoAcademy);
        
        // 为软件学院添加两个专业
        Organization softwareSpeciality1 = new Speciality("软件工程");
        Organization softwareSpeciality2 = new Speciality("网络工程");
        softwareAcademy.add(softwareSpeciality1);
        softwareAcademy.add(softwareSpeciality2);
        
        // 为信息工程学院添加两个专业
        Organization infoSpeciality1 = new Speciality("通信工程");
        Organization infoSpeciality2 = new Speciality("信息工程");
        infoAcademy.add(infoSpeciality1);
        infoAcademy.add(infoSpeciality2);
        
        // 打印该学校的所有学院和专业信息
        school.print();
    }
}

4.优点好处

  • 简化了客户端的操作,客户端不必关心自己处理的是单个对象还是组合对象,不用考虑很复杂的结构问题。
  • 提高了系统的扩展性,符合开闭原则,当我们想添加或移除某个组合对象或者叶子对象的时候,不用对原有的其它对象做任何修改,客户端也不用做任何改动。
  • 提高了系统的可维护性,能够很容易的处理复杂的对象层次关系结构。

5.缺点弊端

  • 由于在这种模式中,客户端需要对所有的组件实现类都能够做统一的操作,所以在增加新的组合对象时,没有办法对其进行一定的限制。
  • 当系统的对象业务非常复杂的时候,组件抽象接口可能需要设置非常多的公共抽象方法,那么组合模式就会有很大的挑战性,因为在叶子对象中,无用的方法可能就会非常多。

6.应用场景

  • 当系统中要处理的对象可以生成一颗树状结构,而我们要对树中的节点和叶子节点进行操作的时候使用,比如:文件结构管理。
  • 当客户端想要使用统一的方式来处理部分对象和整体对象,也就是把部分和整体的关系用树形结构来表示的时候使用。

7.应用示例

JDK源码中的Map集合

通过上方代码我们可以看出,通过Map结构一样可以实现上面我们提到的输出学校组织结构信息的问题。

  1. 下面的Map接口就充当了抽象组件接口,内部封装了put()、putAll()等实现类的公共方法。

  2. 下面的HashMap类就充当了组合对象,实现了Map接口。

  3. 下面的Node内部类就充当了叶子对象,实现了Map接口。

所以通过分析可以看出Map集合的实现也利用到了组合模式

以上是关于设计模式之组合模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之组合模式

设计模式之组合模式

设计模式探秘之组合模式

学习设计模式之组合模式

设计模式之组合模式

PHP设计模式之组合模式