什么是组合模式呢?
组合模式(Composite Pattern),又叫部分整体模式,就是将对象组合成树形结构以表示“部分-整体”的层次结构。它将一些对象按层次关系组织成树形结构,这些对象可能是单个,也可能是组合,然后用同一种逻辑处理这些对象。组合类别属于结构型模式。
哪些使用场景使用呢?
你想表示对象的部分-整体层次结构
你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
光念不好理解哈,举个例子:一个公司,最高层是ceo,下面是销售部、营销部各部门,每个部门也都有自己的员工(经理、员工),当然再往下也可以分各个小组等等。
比如可以将整个公司看作一个整体,每个部门也是一个整体,部门可以是公司的一部分,人员也可以是公司的一部分。公司就像是大树,部门像是枝丫,员工像是叶子,树枝上可以有叶子,叶子就必须是最终节点了。
我们下面用代码来实现这个结构:
1.先建立一个抽象节点对象,抽象出共有属性:
packagecom.xing.design.composite.ep2; /*** * @author xing*/publicabstractclassNode { /*** 名字*/protectedStringname; /*** 工资*/protecteddoublesalary; /*** 人数*/protectedintcount; publicNode(Stringname) { this.name=name; } publicabstractdoublegetAllSalary(); publicabstractintgetAllCount(); publicStringgetName() { returnname; } publicvoidsetName(Stringname) { this.name=name; } publicdoublegetSalary() { returnsalary; } publicvoidsetSalary(doublesalary) { this.salary=salary; } publicintgetCount() { returncount; } publicvoidsetCount(intcount) { this.count=count; } publicStringtoString() { return"Node [name="+name+", salary="+salary+", count="+count+"]"; } }
2.建立部门对象,提供了计算部门的工资和人数的方法:
packagecom.xing.design.composite.ep2; importjava.util.ArrayList; importjava.util.List; /*** 部门* @author xing*/publicclassDepartmentextendsNode{ /*** 存放下级元素*/privateList<Node>subList; publicDepartment(Stringname) { super(name); this.subList=newArrayList<Node>(); } publicdoublegetAllSalary() { doubleallSalary=0; for(Nodenode : subList) { allSalary+=node.getAllSalary(); } this.salary=allSalary; returnallSalary; } publicintgetAllCount() { intallCount=0; for(Nodenode : subList) { allCount+=node.getAllCount(); } this.count=allCount; returnallCount; } publicvoidaddSub(Nodenode) { subList.add(node); } publicList<Node>getSubList(){ returnsubList; } }
3.建立员工对象,员工简单:
packagecom.xing.design.composite.ep2; /*** 员工* @author xing*/publicclassEmployeeextendsNode{ publicEmployee(Stringname, doublesalary) { super(name); this.salary=salary; } publicdoublegetAllSalary() { returnsalary; } publicintgetAllCount() { return1; } }
4.使用上述类来实现部门和员工组成公司的部分-整体结构:
packagecom.xing.design.composite.ep2; /*** 组合模式* 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。* 这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。* 这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。* @author xing*/publicclassCompositePattern { publicstaticvoidmain(String[] args) { // 公司Departmentdepartment=newDepartment("苏念科技"); // 建立头ceoEmployeeCEO=newEmployee("ceo", 300); department.addSub(CEO); department.addSub(newEmployee("混日子人员", 200)); // 销售部门Departmentsales=newDepartment("销售部门"); // 销售头EmployeeheadSales=newEmployee("Robert", 200); // 销售员工1EmployeesalesExecutive1=newEmployee("Richard", 10); // 销售员工2EmployeesalesExecutive2=newEmployee("Rob", 10); sales.addSub(headSales); sales.addSub(salesExecutive1); sales.addSub(salesExecutive2); department.addSub(sales); // 营销部门Departmentmarketing=newDepartment("营销部门"); // 营销头EmployeeheadMarketing=newEmployee("Michel", 20); // 营销员工1Employeeclerk1=newEmployee("Laura", 10); // 营销员工2Employeeclerk2=newEmployee("Bob", 10); marketing.addSub(headMarketing); marketing.addSub(clerk1); marketing.addSub(clerk2); department.addSub(marketing); // 秘书部门Departmentgrils=newDepartment("秘书部"); // 秘书兼财务兼老板娘Employeegril=newEmployee("少妇", 10000); // 二奶Employeegril2=newEmployee("二奶", 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(Nodenode : department.getSubList()) { System.out.println("------------------------打印"+node.getName()+"开始----------------------------"); if(nodeinstanceofDepartment) { DepartmentsubDepartment= (Department) node; for(NodesubNode : 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("------------------------打印本公司所有员工完毕----------------------------"); } }
ok。从Java角度看,我们通过在类中存储成员变量来完成了功能的扩展,玩的就是成员变量。
组合模式组成元素:
- 抽象元素:包含共有元素的类。
- 树叶元素:只包含自身属性的简单对象,没有子节点。
- 树枝元素:包含自身类型的子节点及树叶元素的对象。
- 组合使用类:组合树枝和树叶元素形成树结构的类。
在树型结构的问题中,模糊了简单元素(树叶)和复杂元素(树枝)的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得组合使用类与复杂元素的内部结构解耦。
总结
组合模式就是按照层级关系将不同的对象组装成树形结构,来表达部分和整体的关系。这些对象可以是单个对象(员工),也可以是整体(部门)。
日常中,如果遇到了如角色与菜单、部门与员工、班级与学生、文件夹与文件等业务场景,还有二叉树,我们都可以用组合模式来表示。如一个文件夹里可以有子级文件夹,也可以有文件,子级文件夹下面还可以递归,无线套娃。。。
在组合模式里,我们可以把一个部门看作一个整体,也可以看成公司的一个部分。一个员工可以是一个整体(CEO和混日子那个),也可以是部门或者公司的一部分。我们这样看来就可以一致性的使用单个对象或组合对象,因为都只是一个节点而已。