组合模式

一、组合模式的介绍

1、定义

        组合模式将对象组合成树形结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。组合模式在我们生活中是十分常见的,例如机构的划分。

        组合模式用于将多个对象组合成树形结构以表示“整体-部分”的结构层次,组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。组合模式的关键在于它定义了一个抽象构件类,它既可以表示叶子对象,也可以表示容器对象,客户仅仅需要针对这个抽象构件进行编程,无需知道它是叶子对象还是容器对象,都是一致对待(一碗水平端)。

        组合模式中的角色划分:

  • 抽象构件角色(Component):该角色定义参加组合对象的共有方法和属性,规范一些默认的行为接口。
  • 叶子构件角色(Leaf):该角色是叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为。
  • 树枝构建角色(Composite):该角色代表参加组合的、其下有分支的树枝对象,它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法,如:add()、remove()等。

        组合模式的类图如下:


2、使用场景

  • 需要描述对象的部分和整体的等级结构,如:树形菜单、文件和文件夹管理。
  • 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件。

3、优缺点

(1)优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或者部分层次,从而让增加新的构件也更为容易。
  • 客户端调用简单,客户端可以一致的使用组合结构或者其中的单个对象。
  • 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更为复杂的容器对象,而这个容器对象又可以被组合,这样不断地跪下去,可以形成复杂的树形结构。
  • 更容易在组合体中加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

(2)缺点

  • 不易控制树枝构件的类型。
  • 不易使用继承的方法来增加新的行为。

二、组合模式的实现

场景描述:现实生活中,类似于组合模式的例子很多,这里就用组合模式来实现公司的机构划分。类图如下:

        抽象构件角色:

/**
 * 抽象构件角色
 */
public interface Company {
    String getInfo();
}

        叶子构件角色:

public class Employee implements Company{
    private String name;
    private String position;
    private Double salary;

    public Employee(String name, String position, Double salary) {
        this.name = name;
        this.position = position;
        this.salary = salary;
    }

    @Override
    public String getInfo() {
        return "姓名:" + this.name + "\t" + "职位:" + this.position + "\t" + "薪资:" + this.salary;
    }
}

        树枝构件角色:

public class ConcreteCompany implements Company{
    private String name;
    private String position;
    private Double salary;

    private List<Company> companyList = new ArrayList<>();

    public ConcreteCompany(String name, String position, Double salary) {
        this.name = name;
        this.position = position;
        this.salary = salary;
    }

    public void add(Company company){
        this.companyList.add(company);
    }

    public void remove(Company company){
        this.companyList.remove(company);
    }

    public List<Company> getChild(){
        return this.companyList;
    }

    @Override
    public String getInfo() {
        return "姓名:" + this.name + "\t" + "职位:" + this.position + "\t" + "薪资:" + this.salary;
    }
}

        测试:

public class Client {
    public static void main(String[] args) {
        ConcreteCompany root = new ConcreteCompany("张老大", "董事长", 50000.0);
        ConcreteCompany developDep = new ConcreteCompany("李方", "研发部经理", 30000.0);
        ConcreteCompany saleDep = new ConcreteCompany("孙怛", "销售部经理", 30000.0);
        ConcreteCompany financeDep = new ConcreteCompany("刘华", "财务部经理", 30000.0);
        Employee e1 = new Employee("A", "研发部", 5500.0);
        Employee e2 = new Employee("B", "研发部", 5500.0);
        Employee e3 = new Employee("C", "研发部", 5500.0);
        Employee e4 = new Employee("D", "研发部", 5500.0);
        Employee e5 = new Employee("E", "销售部", 5500.0);
        Employee e6 = new Employee("F", "销售部", 4000.0);
        Employee e7 = new Employee("G", "销售部", 4000.0);
        Employee e8 = new Employee("H", "财务部", 3000.0);
        Employee e9 = new Employee("I", "财务部", 3000.0);
        Employee e10 = new Employee("J", "研发部",5500.0 );
        root.add(developDep);
        root.add(saleDep);
        root.add(financeDep);
        developDep.add(e1);
        developDep.add(e2);
        developDep.add(e3);
        developDep.add(e4);
        developDep.add(e10);
        saleDep.add(e5);
        saleDep.add(e6);
        saleDep.add(e7);
        financeDep.add(e8);
        financeDep.add(e9);
        System.out.println(root.getInfo());
        display(root);
    }

    public static void display(ConcreteCompany root){
        for(Company c : root.getChild()){
            if(c instanceof Employee){
                System.out.println(c.getInfo());
            }else{
                System.out.println("\n" + c.getInfo());
                display((ConcreteCompany) c);
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值