浅谈Java设计模式——组合模式(Composite)
一、概述
将对象组合成树形结构以表示"部分-整体"的层次结构。"Composite使得用户对单个对象和组合对象的使用具有一致性。它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。虽然组合模式能够清晰地定义分层次的复杂对象,也使得增加新构件也更容易,但是这样就导致了系统的设计变得更加抽象,如果系统的业务规则比较复杂的话,使用组合模式就有一定的挑战了。
二、使用场景
1.你想表示对象的部分-整体层次结构。
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
三、参与者
1.Component 为组合中的对象声明接口。 在适当的情况下,实现所有类共有接口的缺省行为。 声明一个接口用于访问和管理Component 的子组件。 (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
2.Leaf 在组合中表示叶节点对象,叶节点没有子节点。 在组合中定义节点对象的行为。
3.Composite 定义有子部件的那些部件的行为。 存储子部件。 在Component接口中实现与子部件有关的操作。
4.Client 通过Component接口操纵组合部件的对象。
四、类图
五、代码示例
1.Component
/**
* Component
* @author zhipeng_Tong
*/
public abstract class Company {
protected 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(); // 履行职责
}
2.Leaf
/**
* Leaf
* @author zhipeng_Tong
*/
public class FinanceDepartment extends Company {
public FinanceDepartment(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(name);
}
@Override
public void lineOfDuty() {
System.out.println(String.format("%s 公司财务收支管理", name));
}
}
/**
* Leap
* @author zhipeng_Tong
*/
public class HRDepartment extends Company {
public HRDepartment(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(name);
}
@Override
public void lineOfDuty() {
System.out.println(String.format("%s 员工招聘培训管理", name));
}
}
3.Composite
/**
* Composite
* @author zhipeng_Tong
*/
public class ConcreteCompany extends Company{
private ArrayList<Company> companies = new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void add(Company company) {
companies.add(company);
}
@Override
public void remove(Company company) {
companies.remove(companies);
}
@Override
public void display(int depth) {
toDisplay(depth);
for (Company c : companies)
c.display(depth + 2);
}
private void toDisplay(int depth) {
for (int i = 0; i < depth; i++)
System.out.print("-");
System.out.println(name);
}
@Override
public void lineOfDuty() {
for (Company c : companies)
c.lineOfDuty();
}
}
4.Client 通过Component接口操纵组合部件的对象。
public class Client {
public static void main(String[] args) {
ConcreteCompany root = new ConcreteCompany("北京总公司");
root.add(new HRDepartment("总公司人力资源部"));
root.add(new FinanceDepartment("总公司财务部"));
ConcreteCompany company = new ConcreteCompany("上海华东分公司");
company.add(new HRDepartment("上海华东分公司人力资源部"));
company.add(new FinanceDepartment("上海华东分公司人财务部"));
root.add(company);
ConcreteCompany company2 = new ConcreteCompany("南京办事处");
company2.add(new HRDepartment("南京办事处人力资源部"));
company2.add(new FinanceDepartment("南京办事处人财务部"));
company.add(company2);
ConcreteCompany company3 = new ConcreteCompany("吉林东北分公司");
company3.add(new HRDepartment("吉林东北分公司人力资源部"));
company3.add(new FinanceDepartment("吉林东北分公司人财务部"));
root.add(company3);
ConcreteCompany company4 = new ConcreteCompany("长春办事处");
company4.add(new HRDepartment("长春办事处人力资源部"));
company4.add(new FinanceDepartment("长春办事处人财务部"));
company3.add(company4);
System.out.println("结构图:");
root.display(1);
System.out.println("职责:");
root.lineOfDuty();
}
}
运行结果
结构图:
-北京总公司
---总公司人力资源部
---总公司财务部
---上海华东分公司
-----上海华东分公司人力资源部
-----上海华东分公司人财务部
-----南京办事处
-------南京办事处人力资源部
-------南京办事处人财务部
---吉林东北分公司
-----吉林东北分公司人力资源部
-----吉林东北分公司人财务部
-----长春办事处
-------长春办事处人力资源部
-------长春办事处人财务部
职责:
总公司人力资源部 员工招聘培训管理
总公司财务部 公司财务收支管理
上海华东分公司人力资源部 员工招聘培训管理
上海华东分公司人财务部 公司财务收支管理
南京办事处人力资源部 员工招聘培训管理
南京办事处人财务部 公司财务收支管理
吉林东北分公司人力资源部 员工招聘培训管理
吉林东北分公司人财务部 公司财务收支管理
长春办事处人力资源部 员工招聘培训管理
长春办事处人财务部 公司财务收支管理