复合模式是一种分区设计模式,它描述了一组对象,这些对象的处理方式与同一类型对象的单个实例相同。复合的目的是将对象“组合”成树结构以表示部分-整体层次结构。它允许您拥有树结构并要求树结构中的每个节点执行任务。
- 正如 Gof 所描述的那样,“将对象组合成树结构以表示部分-整体层次结构。 Composite 让客户可以统一处理单个对象和对象的组合”。
- 在处理树结构数据时,程序员通常必须区分叶节点和分支。这使得代码更加复杂,因此容易出错。解决方案是一个允许统一处理复杂和原始对象的接口。
- 在面向对象的编程中,组合是一个对象,它被设计为一个或多个相似对象的组合,所有这些对象都表现出相似的功能。这被称为对象之间的“has-a”关系。
关键概念是您可以操作对象的单个实例,就像操作一组对象一样。您可以对所有复合对象执行的操作通常具有最小公分母关系。
复合模式有四个参与者:- 组件 –组件声明组合中对象的接口以及用于访问和管理其子组件的接口。它还根据需要为所有类通用的接口实现默认行为。
- 叶 –叶定义组合中原始对象的行为。它代表组合中的叶对象。
- Composite – Composite 存储子组件并在组件接口中实现与子相关的操作。
- 客户端——客户端通过组件接口操作组合中的对象。
客户端使用组件类接口与组合结构中的对象进行交互。如果接收者是叶子,则直接处理请求。如果接收者是一个组合,那么它通常会将请求转发到它的子组件,可能在转发之前和之后执行额外的操作。
现实生活中的例子
在一个组织中,它有总经理,总经理下可以有经理,经理下可以有开发人员。现在您可以设置树结构并要求每个节点执行诸如 getSalary() 之类的常见操作。
复合设计模式以两种方式处理每个节点:
1) Composite – Composite 意味着它下面可以有其他对象。
2)叶子——叶子意味着它下面没有物体。树结构:
上图显示了一个典型的复合对象结构。如您所见,单个父级(即 Composite)可以有多个子级,但每个子级只能有一个父级。接口组件。Java
public interface Employee { public void showEmployeeDetails(); }
叶子。Java
public class Developer implements Employee { private String name; private long empId; private String position; public Developer(long empId, String name, String position) { this.empId = empId; this.name = name; this.position = position; } @Override public void showEmployeeDetails() { System.out.println(empId+" " +name+); } }
叶子。Java
public class Manager implements Employee { private String name; private long empId; private String position; public Manager(long empId, String name, String position) { this.empId = empId; this.name = name; this.position = position; } @Override public void showEmployeeDetails() { System.out.println(empId+" " +name); } }
合成的。Java
import java.util.ArrayList; import java.util.List; public class CompanyDirectory implements Employee { private List
employeeList = new ArrayList (); @Override public void showEmployeeDetails() { for(Employee emp:employeeList) { emp.showEmployeeDetails(); } } public void addEmployee(Employee emp) { employeeList.add(emp); } public void removeEmployee(Employee emp) { employeeList.remove(emp); } } 客户。Java
public class Company { public static void main (String[] args) { Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer"); Developer dev2 = new Developer(101, "Vinay Sharma", "Developer"); CompanyDirectory engDirectory = new CompanyDirectory(); engDirectory.addEmployee(dev1); engDirectory.addEmployee(dev2); Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager"); Manager man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager"); CompanyDirectory accDirectory = new CompanyDirectory(); accDirectory.addEmployee(man1); accDirectory.addEmployee(man2); CompanyDirectory directory = new CompanyDirectory(); directory.addEmployee(engDirectory); directory.addEmployee(accDirectory); directory.showEmployeeDetails(); } }
复合设计模式的 UML 图:
上面例子的完整运行代码:
// A Java program to demonstrate working of // Composite Design Pattern with example // of a company with different // employee details import java.util.ArrayList; import java.util.List; // A common interface for all employee interface Employee { public void showEmployeeDetails(); } class Developer implements Employee { private String name; private long empId; private String position; public Developer(long empId, String name, String position) { // Assign the Employee id, // name and the position this.empId = empId; this.name = name; this.position = position; } @Override public void showEmployeeDetails() { System.out.println(empId+" " +name+ " " + position ); } } class Manager implements Employee { private String name; private long empId; private String position; public Manager(long empId, String name, String position) { this.empId = empId; this.name = name; this.position = position; } @Override public void showEmployeeDetails() { System.out.println(empId+" " +name+ " " + position ); } } // Class used to get Employee List // and do the opertions like // add or remove Employee class CompanyDirectory implements Employee { private List
employeeList = new ArrayList (); @Override public void showEmployeeDetails() { for(Employee emp:employeeList) { emp.showEmployeeDetails(); } } public void addEmployee(Employee emp) { employeeList.add(emp); } public void removeEmployee(Employee emp) { employeeList.remove(emp); } } // Driver class public class Company { public static void main (String[] args) { Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer"); Developer dev2 = new Developer(101, "Vinay Sharma", "Developer"); CompanyDirectory engDirectory = new CompanyDirectory(); engDirectory.addEmployee(dev1); engDirectory.addEmployee(dev2); Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager"); Manager man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager"); CompanyDirectory accDirectory = new CompanyDirectory(); accDirectory.addEmployee(man1); accDirectory.addEmployee(man2); CompanyDirectory directory = new CompanyDirectory(); directory.addEmployee(engDirectory); directory.addEmployee(accDirectory); directory.showEmployeeDetails(); } } 输出 :
100 Lokesh Sharma Pro Developer 101 Vinay Sharma Developer 200 Kushagra Garg SEO Manager 201 Vikram Sharma Kushagra's Manager
什么时候使用复合设计模式?
当客户需要忽略对象的组合和单个对象之间的差异时,应该使用复合模式。如果程序员发现他们以相同的方式使用多个对象,并且通常有几乎相同的代码来处理每个对象,那么复合是一个不错的选择,在这种情况下,将基元和复合视为同构并不那么复杂。
- 更少的对象减少了内存使用量,它设法让我们远离与内存相关的错误,如Java.lang.OutOfMemoryError。
- 尽管在Java创建对象确实很快,但我们仍然可以通过共享对象来减少程序的执行时间。
什么时候不使用复合设计模式?
- 复合设计模式使得限制复合组件的类型变得更加困难。因此,当您不想表示对象的完整或部分层次结构时,不应使用它。
- 复合设计模式会使设计过于笼统。限制复合材料的组件变得更加困难。有时您希望复合材料仅包含某些组件。使用 Composite,您不能依赖类型系统来为您强制执行这些约束。相反,您必须使用运行时检查。