组合模式




组合模式


1. 介绍

组合模式(Composite Pattern)是一种结构型模式。将对象进行组合来达到类似于数这种层级关系。

简单理解:假设一个公司只有一个老板,有几个CEO,每一个CEO下面又有1个或多个组长,而每个组长下面又会有若干名员工,这是不是很像数据结构中的树,老板就是根节点,CEO和组长下面可以有若干子节点,而员工就是叶子节点,因为员工下面是没有子节点的(员工不管理任何人)


优点

  1. 很方便的表示各个对象之间的层级关系。由于组合模式是用类似于数的结构来组织对象,因此,数这种数据结构能够清晰表示层次关系的优点也被继承下来了。所以,文件系统、公司人员关系等都可以采用组合模式。
  2. 对象中嵌套其他对象很方便。组合模式中的对象会使用一个链表(其他数据类型)来存储其下一层对象,所以,基本对象可以被组合成更为复杂的对象,而复杂对象可以再次被组合成更复杂的对象,以此类推。

缺点

  1. 实现比较复杂。因为组合模式会牵扯到数的知识,而数的遍历、节点的删除、查找节点、添加节点又会使用到类似于递归、队列、遍历、查询等知识,是不是头都大了。
  2. 违反了依赖倒置原则。组合模式中的枝干和叶子都声明成了对象,而不是接口,这违反了依赖倒置原则。

2. 例子

我们使用组合模式来实现一个公司中人员的层次关系。


类图

在这里插入图片描述


Employee类
代表员工对象,在对象中使用List(其他数据结构也可以)来储存它的下属对象。

package CompositePattern;

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

public class Employee {
    private String name;
    private String dept;
    private double salary;
    private List<Employee> subordinates;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public List<Employee> getSubordinates() {
        return subordinates;
    }

    public void setSubordinates(List<Employee> subordinates) {
        this.subordinates = subordinates;
    }

    public Employee(String name, String dept, double salary) {
        this.salary = salary;
        this.name = name;
        this.dept = dept;
        subordinates = new ArrayList<Employee>();
    }

    public boolean add(Employee employee) {
        return subordinates.add(employee);
    }

    public boolean remove(Employee employee) {
        return subordinates.remove(employee);
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", dept=" + dept + ", salary=" + salary + ", subordinates=" + subordinates
                + "]";
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public void dfs() {
        dfs(this);
    }

    //深度优先算法
    public void dfs(Employee employee) {
        System.out.println(employee.toString());
        if (employee != null && !employee.getSubordinates().isEmpty()) {
            for (Employee subordinate : employee.subordinates) {
                dfs(subordinate);
            }
        } else {
            return;
        }
    }

    //广度优先
    public void bfs(Employee employee) {
        Stack<Employee> stack = new Stack<Employee>();
        stack.add(employee);
        while (!stack.isEmpty()) {
            System.out.println(stack.peek().toString());
            Employee temEmployee = stack.pop();
            for (Employee subordinates : temEmployee.getSubordinates()) {
                if (subordinates != null) {
                    stack.add(subordinates);
                }
            }
        }
    }

    public void bfs() {
        bfs(this);
    }

}

测试类
构造一个公司的成员逻辑结构,分别调用深度优先和广度优先算法来遍历这个层级结构。

package CompositePattern;


import org.junit.Test;

public class TestJ {
    @Test
    public void test1() {
        Employee header = new Employee("刘老板", "headers", 23000);
        
        Employee CEO1 = new Employee("ceo小明", "ceo", 12000);
        Employee CEO2 = new Employee("ceo小红", "ceo", 12000);
        
        Employee groupLeader1 = new Employee("组长", "groupLeader", 6000);
        Employee groupLeader2 = new Employee("组长", "groupLeader", 6000);
        
        Employee employee1 = new Employee("员工1", "employee", 2000);
        Employee employee2 = new Employee("员工2", "employee", 2000);
        Employee employee3 = new Employee("员工3", "employee", 2000);
        Employee employee4 = new Employee("员工4", "employee", 2000);
        Employee employee5 = new Employee("员工5", "employee", 2000);
        
        groupLeader1.add(employee1);
        groupLeader1.add(employee2);
        groupLeader2.add(employee3);
        groupLeader2.add(employee4);
        groupLeader2.add(employee5);
        
        CEO1.add(groupLeader1);
        CEO2.add(groupLeader2);
        
        header.add(CEO1);
        header.add(CEO2);
        
        //广度优先算法
        header.bfs();
        
        System.out.println("-------------------");
        
        //深度优先算法
        header.dfs();
        
    }
}

运行结果:

Employee [name=刘老板, dept=headers, salary=23000.0, subordinates=[Employee [name=ceo小明, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]]], Employee [name=ceo小红, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]]]]]
Employee [name=ceo小红, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]]]
Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]
Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=ceo小明, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]]]
Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]
Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]]
-------------------
Employee [name=刘老板, dept=headers, salary=23000.0, subordinates=[Employee [name=ceo小明, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]]], Employee [name=ceo小红, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]]]]]
Employee [name=ceo小明, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]]]
Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]]]
Employee [name=员工1, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工2, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=ceo小红, dept=ceo, salary=12000.0, subordinates=[Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]]]
Employee [name=组长, dept=groupLeader, salary=6000.0, subordinates=[Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]], Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]]]
Employee [name=员工3, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工4, dept=employee, salary=2000.0, subordinates=[]]
Employee [name=员工5, dept=employee, salary=2000.0, subordinates=[]]

3. 总结

组合模式在类中使用一个列表或其他数据结构来存储其下属对象(子节点),类似于树,用来明了的表示对象之间的层次结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值