开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第四天,点击查看活动详情
PS:已经更文多少天,N就写几。一定要写对文案,否则文章不计入在内;模板句子需要带超链接。
什么是组合模式呢?
组合模式(Composite Pattern),又叫部分整体模式,就是将对象组合成树形结构以表示“部分-整体”的层次结构。它将一些对象按层次关系组织成树形结构,这些对象可能是单个,也可能是组合,然后用同一种逻辑处理这些对象。组合类别属于结构型模式。
哪些使用场景使用呢?
你想表示对象的部分-整体层次结构
你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
光念不好理解哈,举个例子:一个公司,最高层是ceo,下面是销售部、营销部各部门,每个部门也都有自己的员工(经理、员工),当然再往下也可以分各个小组等等。
如图:
如图所示,可以将整个公司看作一个整体,每个部门也是一个整体,部门可以是公司的一部分,人员也可以是公司的一部分。公司就像是大树,部门像是枝丫,员工像是叶子,树枝上可以有叶子,叶子就必须是最终节点了。
一、我们下面用代码来实现这个结构:
1.先建立一个抽象节点对象,抽象出共有属性:
package com.xing.design.composite.ep2;
/**
*
* @author xing
*/
public abstract class Node {
/**
* 名字
*/
protected String name;
/**
* 工资
*/
protected double salary;
/**
* 人数
*/
protected int count;
public Node(String name) {
this.name= name;
}
public abstract double getAllSalary();
public abstract int getAllCount();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Node [name=" + name + ", salary=" + salary + ", count=" + count + "]";
}
}
2.建立部门对象,提供了计算部门的工资和人数的方法:
package com.xing.design.composite.ep2;
import java.util.ArrayList;
import java.util.List;
/**
* 部门
* @author xing
*/
public class Department extends Node{
/**
* 存放下级元素
*/
private List<Node> subList;
public Department(String name) {
super(name);
this.subList = new ArrayList<Node>();
}
@Override
public double getAllSalary() {
double allSalary = 0;
for(Node node : subList) {
allSalary += node.getAllSalary();
}
this.salary = allSalary;
return allSalary;
}
@Override
public int getAllCount() {
int allCount = 0;
for(Node node : subList) {
allCount += node.getAllCount();
}
this.count = allCount;
return allCount;
}
public void addSub(Node node) {
subList.add(node);
}
public List<Node> getSubList(){
return subList;
}
}
3.建立员工对象,员工简单:
package com.xing.design.composite.ep2;
/**
* 员工
* @author xing
*/
public class Employee extends Node{
public Employee(String name, double salary) {
super(name);
this.salary = salary;
}
@Override
public double getAllSalary() {
return salary;
}
@Override
public int getAllCount() {
return 1;
}
}
4.使用上述类来实现部门和员工组成公司的部分-整体结构:
package com.xing.design.composite.ep2;
/**
* 组合模式
* 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
* 这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
* 这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
* @author xing
*/
public class CompositePattern {
public static void main(String[] args) {
// 公司
Department department = new Department("苏念科技");
// 建立头ceo
Employee CEO = new Employee("ceo", 300);
department.addSub(CEO);
department.addSub(new Employee("混日子人员", 200));
// 销售部门
Department sales = new Department("销售部门");
// 销售头
Employee headSales = new Employee("Robert", 200);
// 销售员工1
Employee salesExecutive1 = new Employee("Richard", 10);
// 销售员工2
Employee salesExecutive2 = new Employee("Rob", 10);
sales.addSub(headSales);
sales.addSub(salesExecutive1);
sales.addSub(salesExecutive2);
department.addSub(sales);
// 营销部门
Department marketing = new Department("营销部门");
// 营销头
Employee headMarketing = new Employee("Michel", 20);
// 营销员工1
Employee clerk1 = new Employee("Laura", 10);
// 营销员工2
Employee clerk2 = new Employee("Bob", 10);
marketing.addSub(headMarketing);
marketing.addSub(clerk1);
marketing.addSub(clerk2);
department.addSub(marketing);
// 秘书部门
Department grils = new Department("秘书部");
// 秘书兼财务兼老板娘
Employee gril = new Employee("少妇", 10000);
// 二奶
Employee gril2 = new Employee("二奶", 1000);
grils.addSub(gril);
grils.addSub(gril2);
department.addSub(grils);
System.out.println("公司总工资:"+department.getAllSalary());
System.out.println("公司总人数:"+department.getAllCount());
System.out.println("公司平均工资:"+department.getAllSalary() / department.getAllCount());
System.out.println("------------------------打印本公司所有员工开始----------------------------");
//公司
System.out.println("公司:"+department.getName());
//公司人员
for(Node node : department.getSubList()) {
System.out.println("------------------------打印"+node.getName()+"开始----------------------------");
if(node instanceof Department) {
Department subDepartment = (Department) node;
for(Node subNode : subDepartment.getSubList()) {
System.out.println(node.getName()+"部门内人员:"+subNode);
}
}else {
System.out.println("人员:"+node.getName());
}
System.out.println("------------------------打印"+node.getName()+"结束----------------------------");
System.out.println("");
}
System.out.println("------------------------打印本公司所有员工完毕----------------------------");
}
}
5.测试结果
ok。从Java角度看,我们通过在类中存储成员变量来完成了功能的扩展,玩的就是成员变量。
组合模式组成元素:
抽象元素:包含共有元素的类。
树叶元素:只包含自身属性的简单对象,没有子节点。
树枝元素:包含自身类型的子节点及树叶元素的对象。
组合使用类:组合树枝和树叶元素形成树结构的类。
在树型结构的问题中,模糊了简单元素(树叶)和复杂元素(树枝)的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得组合使用类与复杂元素的内部结构解耦。
总结:
组合模式就是按照层级关系将不同的对象组装成树形结构,来表达部分和整体的关系。这些对象可以是单个对象(员工),也可以是整体(部门)。
日常中,如果遇到了如角色与菜单、部门与员工、班级与学生、文件夹与文件等业务场景,还有二叉树,我们都可以用组合模式来表示。如一个文件夹里可以有子级文件夹,也可以有文件,子级文件夹下面还可以递归,无线套娃。。。
在组合模式里,我们可以把一个部门看作一个整体,也可以看成公司的一个部分。一个员工可以是一个整体(CEO和混日子那个),也可以是部门或者公司的一部分。我们这样看来就可以一致性的使用单个对象或组合对象,因为都只是一个节点而已。
END
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第四天,点击查看活动详情
PS:已经更文多少天,N就写几。一定要写对文案,否则文章不计入在内;模板句子需要带超链接。