组合模式——一致地使用多个对象
2019-10-19 本文已影响0人
方才编程
一、基础简介
1、定义
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
2、使用场景
当需求中是体现部分与整体层次的结构时,同时希望用户可以忽略组合对象与单个对象的不同,统一使用组合结构中的所有对象时,就考虑使用该模式
3、优缺点
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
4、模式结构解析
该模式有三个角色:Component、Leaf、Composite,关于角色介绍请看下图:
二、模式实例实现
1、场景
一个大型公司,会有一个“总公司”,多个“分公司”,“分公司”下还会有“办事处”,但相同的是,都会有一些共同的职能部门,比如说“人力资源部”,“财务部”等。
2、Component 是组合中的对象声明接口:抽象公司类
package com.mfc.design.组合模式;
/**
* @author MouFangCai
* @date 2019/10/19 16:40
*
* Component:组合中的对象申明接口
*/
public abstract class Company {
private String name;
public Company(String name) {
this.name = name;
}
public abstract void add(Company company);
public abstract void remove(Company company);
public abstract void display(int depth);
// “履行职责”方法,不同的部门需要履行不同的职责
public abstract void lineOfDuty();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、Composite 定义有枝节点行为,用来存储子部件:具体公司类
package com.mfc.design.组合模式;
import java.util.ArrayList;
import java.util.List;
/**
* @author MouFangCai
* @date 2019/10/19 16:46
*
* Composite:定义有支节点行为,用来存储子部件
*/
public class ConcreteCompany extends Company {
private List<Company> childrens = new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void add(Company company) {
childrens.add(company);
}
@Override
public void remove(Company company) {
childrens.remove(company);
}
// 层级展示
@Override
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println(getName());
for (Company c : childrens) {
c.display(depth + 2);
}
}
// 部门职责
@Override
public void lineOfDuty() {
for (Company c : childrens) {
c.lineOfDuty();
}
}
}
4、Leaf 在组合中表示叶子结点对象,叶子结点没有子结点
package com.mfc.design.组合模式;
/**
* @author MouFangCai
* @date 2019/10/19 17:06
*
* Leaf:在组合中表示叶节点对象,叶节点没有子节点
*/
public class HR_Department extends Company {
public HR_Department(String name) {
super(name);
}
// 由于“叶子”没有再增加分支和树叶的能力,所以add()和remove()实现是没有意义的
@Override
public void add(Company company) {
}
@Override
public void remove(Company company) {
}
// 展示具体的名称和级别
@Override
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println(getName());
}
@Override
public void lineOfDuty() {
System.out.println(getName() + ": 负责招聘");
}
}
package com.mfc.design.组合模式;
/**
* @author MouFangCai
* @date 2019/10/19 17:16
*/
public class Finance_Department extends Company {
public Finance_Department(String name) {
super(name);
}
@Override
public void add(Company company) {
}
@Override
public void remove(Company company) {
}
@Override
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println(getName());
}
@Override
public void lineOfDuty() {
System.out.println(getName() + ":负责财务结算");
}
}
5、客户端
package com.mfc.design.组合模式;
/**
* @author MouFangCai
* @date 2019/10/19 17:17
*/
public class Client_Component {
public static void main(String[] args) {
ConcreteCompany root = new ConcreteCompany("mfc总公司");
root.add(new HR_Department("总公司-HR部"));
root.add(new Finance_Department("总公司-财务部"));
// 一级分公司
ConcreteCompany subComp01 = new ConcreteCompany("01分公司");
subComp01.add(new HR_Department("01分公司-HR部"));
subComp01.add(new Finance_Department("01分公司-财务部"));
root.add(subComp01);
// 二级办事处
ConcreteCompany subComp02 = new ConcreteCompany("01办事处");
subComp02.add(new HR_Department("01办事处-HR部"));
subComp02.add(new Finance_Department("01办事处-财务部"));
subComp01.add(subComp02);
System.out.println("\n公司架构图:");
root.display(1);
System.out.println("\n部门职责详情:");
root.lineOfDuty();
}
}
6、结果展示
公司架构图:
-mfc总公司
---总公司-HR部
---总公司-财务部
---01分公司
-----01分公司-HR部
-----01分公司-财务部
-----01办事处
-------01办事处-HR部
-------01办事处-财务部部门职责详情:
总公司-HR部: 负责招聘
总公司-财务部:负责财务结算
01分公司-HR部: 负责招聘
01分公司-财务部:负责财务结算
01办事处-HR部: 负责招聘
01办事处-财务部:负责财务结算Process finished with exit code 0