设计模式 —— 组合模式(Composite Pattern)

组合模式(Composite Pattern)

概念:

定义:组合模式 允许你将对象组合成树型结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。


在日常生活中我们经常会遇到树型结构的问题,比如典型的公司管理,上司管理不同的下属,下属也可能属于某个部门的上司。

组合模式

组合模式可以模糊简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。


组成:

组合模式

Component(组合):为组合中的所有对象定义一个接口。包括组合和叶节点。

Leaf(叶节点):叶节点通过实现了 Composite 支持的操作,定义了这内元素的行为。

Composite(组件):定义组件的行为,并且组件也拥有子节点。


例子:

公司雇员例子,CEO 有雇员,雇员中有部门经理,经理地面又有雇员。

组件类:
所有的组件都必须实现该接口,然而叶节点和组合节点的角色不同,所以有些方法可能并不适合某种节点。遇到这种情况时,有时候最好的方式是抛出运行时异常。

public abstract class EmployeeConponent {
    private String name;
    private String description;
    private double salary;

    //构造函数,包括姓名、描述、薪水
    public EmployeeConponent(String name, String description, double salary) {
        this.name = name;
        this.description = description;
        this.salary = salary;
    }

    //添加雇员
    public void add(EmployeeConponent employeeConponent) {
        throw new UnsupportedOperationException();
    }

    //删除雇员
    public void remove(EmployeeConponent employeeConponent) {
        throw new UnsupportedOperationException();
    }

    //获得某一个子节点
    public Object getChild(int i) {
        throw new UnsupportedOperationException();
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public double getSalary() {
        return salary;
    }

    public void print() {
        System.out.print("name:" + name);
        System.out.print(" description:" + description);
        System.out.println(" salary:" + salary);
    }
}

Boss 类:

public class Boss extends EmployeeConponent {
    //雇员列表
    ArrayList<EmployeeConponent> subordinates;

    public Boss(String name, String description, double salary) {
        super(name, description, salary);
        subordinates = new ArrayList<EmployeeConponent>();
    }

    @Override
    public void add(EmployeeConponent employeeConponent) {
        subordinates.add(employeeConponent);
    }

    @Override
    public void remove(EmployeeConponent employeeConponent) {
        subordinates.remove(employeeConponent);
    }

    @Override
    public EmployeeConponent getChild(int i) {
        return (EmployeeConponent) subordinates.get(i);
    }

    //打印自己以及雇员
    @Override
    public void print() {
        System.out.print("name:" + super.getName());
        System.out.print(" description:" + super.getDescription());
        System.out.println(" salary:" + super.getSalary());
        for (EmployeeConponent i : subordinates) {
            i.print();
        }
        System.out.println();
    }
}

雇员类:

public class Employee extends EmployeeConponent {
    public Employee(String name, String description, double salary) {
        super(name, description, salary);
    }
}

测试类:

public class Client {
    public static void main(String[] args) {
        Boss CEO = new Boss("Li", "CEO", 25000);

        Employee employee1 = new Employee("Zhang", "Employee", 12000);
        Employee employee2 = new Employee("Zhao", "Employee", 12000);

        Boss manager = new Boss("Wang", "Manager", 20000);

        Employee employee3 = new Employee("He", "Employee", 12000);
        Employee employee4 = new Employee("Qi", "Empoyee", 12000);

        CEO.add(employee1);
        CEO.add(employee2);
        CEO.add(manager);
        manager.add(employee3);
        manager.add(employee4);

        CEO.print();
    }
}

组合模式


适用场景:

  • 当我们想表示对象的部分-整体层次结构(树形结构,如文件系统、雇员关系等)。
  • 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
  • 组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以向处理简单元素一样来处理复杂元素。
    如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。

优缺点:

优点:

  • 高层模块调用简单,组合模式解耦了客户程序与复杂元素内部结构。从而使客户程序可以向处理简单元素一样来处理复杂元素。创建层次结构,并可以在其中以相同的方式对待所有元素。
  • 节点可以自由增加。

缺点:

  • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

依赖倒置原则:要依赖抽象,不要依赖具体类。

这个原则说明:不能让高层组件依赖底层组件,而且,不管是高层组件或底层组件,都应该依赖于抽象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏天的技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值