设计模式之组合模式

来源:互联网 发布:社会网络分析大数据 编辑:程序博客网 时间:2024/06/07 06:56

前言

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

一.组合模式简介

组合模式(Composite Pattern)又叫部分整体模式,隶属于结构型模式,将对象组装成树形结构,该模式创建了一个包含自己对象组的类,用以修改相同的对象组。

二.组合模式的实例讲解

案例:公司的组织架构对象,用组合模式来管理,总公司包含各个地方的分公司,分公司又包含不同的部门,但是每个分公司的部门基本相同,像这样的树形对象,可以用组合模式来进行管理实现。

1.产品设计UML类图

这里写图片描述
(图片加载慢,多刷新几下,耐心等待……)

注:具体公司类ConcreteCompany和公司类Company是聚合关系,ConcreteCompany包含Company,但不是Company的一部分。

聚合关系:表示一种弱的"拥有"关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。

2.公司抽象类

设计分析:组合中的抽象声明接口,实现所有类的共有接口和默认行为,并声明一个接口,管理子部件。本例中用Company对象来管理各个分公司以及部门对象。

package com.pattern.composite.component;/** * 公司抽象类 * */public abstract class Company {    protected String name;    public Company(String name) {        this.name = name;    }    public abstract void add(Company com);//添加对象    public abstract void remove(Company com);//删除对象    public abstract void show(int level);//显示对象信息    public abstract void doWork();//运营部门任务}

3.具体公司类

设计分析: 一个具体公司的对象,继承Company,实现父类方法,进行管理子公司或者部门。

package com.pattern.composite.composite;import java.util.ArrayList;import java.util.List;import com.pattern.composite.component.Company;/** * 具体公司类 *  */public class ConcreteCompany extends Company {    //管理子公司以及其部门的集合    private List<Company> leafCompanyList = new ArrayList<>();    public ConcreteCompany(String name) {        super(name);    }    @Override    public void add(Company com) {        leafCompanyList.add(com);    }    @Override    public void remove(Company com) {        leafCompanyList.remove(com);    }    @Override    public void show(int level) {        System.out.println();        // 打印横线+部门名        System.out.println(new String(new char[] { '-', '-', '-', '-', '-', '-', '-' }, 0, level) + name);        for (Company c : leafCompanyList) {            c.show(level + 2);// 为现实层级结构,每多一层部门,横线递增2条        }    }    @Override    public void doWork() {        System.out.println();        for (Company c : leafCompanyList) {            c.doWork();        }    }}

4.部门类

设计分析: 所有子公司都具备销售部门和售后服务部门,该部门对象也继承Company,实现父类的方法。

代码如下:

销售部门类:
package com.pattern.composite.composite;import com.pattern.composite.component.Company;/** * 销售部门 * */public class SaleDepartment extends Company {    public SaleDepartment(String name) {        super(name);    }    @Override    public void add(Company com) {    }    @Override    public void remove(Company com) {    }    @Override    public void show(int level) {        // 打印横线+部门名        System.out.println(new String(new char[] { '-', '-', '-', '-', '-', '-', '-' }, 0, level) + name);    }    @Override    public void doWork() {        System.out.println(name+"开展产品促销活动");    }}
售后服务部门类:
package com.pattern.composite.composite;import com.pattern.composite.component.Company;/** * 售后服务部门 *  */public class AfterSaleDepartment extends Company {    public AfterSaleDepartment(String name) {        super(name);    }    @Override    public void add(Company com) {    }    @Override    public void remove(Company com) {    }    @Override    public void show(int level) {        // 打印横线+部门名        System.out.println(new String(new char[] { '-', '-', '-', '-', '-', '-', '-' }, 0, level) + name);    }    @Override    public void doWork() {        System.out.println(name + "处理产品售后问题");    }}

5.客户端中使用

在总公司下,有三个地方分公司,每个分公司都包含两个部门(销售部和售后部),模拟树形结构对象的管理操作。

package com.pattern.composite.client;import com.pattern.composite.composite.AfterSaleDepartment;import com.pattern.composite.composite.ConcreteCompany;import com.pattern.composite.composite.SaleDepartment;public class Client {    public static void main(String[] args) {        ConcreteCompany rootCom = new ConcreteCompany("芒果公司总部");        rootCom.add(new SaleDepartment("芒果总公司销售部"));        rootCom.add(new AfterSaleDepartment("芒果总公司售后部"));        ConcreteCompany sdCom = new ConcreteCompany("山东芒果分公司");        sdCom.add(new SaleDepartment("山东芒果分公司销售部"));        sdCom.add(new AfterSaleDepartment("山东芒果分公司售后部"));        rootCom.add(sdCom);        ConcreteCompany twCom = new ConcreteCompany("台湾芒果分公司");        twCom.add(new SaleDepartment("台湾芒果分公司销售部"));        twCom.add(new AfterSaleDepartment("台湾芒果分公司售后部"));        rootCom.add(twCom);        ConcreteCompany dydCom = new ConcreteCompany("钓鱼岛芒果分公司");        dydCom.add(new SaleDepartment("钓鱼岛芒果分公司销售部"));        dydCom.add(new AfterSaleDepartment("钓鱼岛芒果分公司售后部"));        rootCom.add(dydCom);        System.out.println("---公司组织架构图---");        rootCom.show(1);        System.out.println();        System.out.println("---公司运营情况---");        rootCom.doWork();    }}

6.运行结果展示

---公司组织架构图----芒果公司总部---芒果总公司销售部---芒果总公司售后部---山东芒果分公司-----山东芒果分公司销售部-----山东芒果分公司售后部---台湾芒果分公司-----台湾芒果分公司销售部-----台湾芒果分公司售后部---钓鱼岛芒果分公司-----钓鱼岛芒果分公司销售部-----钓鱼岛芒果分公司售后部---公司运营情况---芒果总公司销售部开展产品促销活动芒果总公司售后部处理产品售后问题山东芒果分公司销售部开展产品促销活动山东芒果分公司售后部处理产品售后问题台湾芒果分公司销售部开展产品促销活动台湾芒果分公司售后部处理产品售后问题钓鱼岛芒果分公司销售部开展产品促销活动钓鱼岛芒果分公司售后部处理产品售后问题

7.源码下载

本文示例代码下载地址:点击下载

三.总结:

组合模式定义了包含销售部和售后部这些基本对象和分公司等组合对象的类层次结构,一个基本的对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断递归,客户端中,任何用到基本对象的地方都可以用到组合对象了。

1.组合模式的优点

  • 方便客户端统一调用,不需要关心处理了一个叶节点还是一个组合组件。
  • 可以自由的新增节点,自由组合节点。

2.组合模式的缺点

  • 违反依赖倒转原则,子节点都是实现类,上层模块依赖了下层模块,一旦下层模块修改,上层便不能使用了。