如何在 Java 中使用复合设计模式?
你好 Java 程序员,如果大家想了解 Java 中的复合设计模式,例如如何实现复合设计模式以及何时使用它,那么来对地方了。 在本文中,我们将讨论复合设计模式。 复合设计模式(Composite Design Pattern) 是 GOF 的一种行为设计模式,首先在他们的经典书籍设计模式中进行了描述。 组合模式允许我们将结构构建为树,其中包含叶和组合。
叶子是一个对象,对应于树中的一个叶子节点,不包含其他对象,而复合对象包含其他组合或叶子。 这种设计模式最强大的特性之一是我们可以用相同的方式处理叶子和组合。
例如,我们有一个组织结构图,其中包含按层级顺序排列的每个员工。 有些员工是经理,他们包含对向他们报告的其他员工的参考。 如果我们需要直接打印员工列表的所有内容,则必须检查特定员工是否是经理才能执行此操作。
删除此检查的一种方法是使用复合模式,它允许以相同的方式对待普通员工和经理,这就是我们将在本篇文章中看到的内容。 我们将使用这个例子来实现 Java 中的复合设计模式。
什么是复合设计模式? 一个例子
下面是 Java 中复合模式的示例。 在这里,我们使用复合模式来表示组织中的员工。 这里有些员工是经理,他们是复合对象,因为它们包含对向他们报告的其他员工的引用。
如果我们需要为员工列表打印指令(向他报告的员工),我们不能在不检查该员工是否为经理的情况下执行此操作。 删除此检查的一种方法是使用复合模式,它允许以相同的方式对待普通员工和经理。
在复合设计模式中,我们有一个 Component
对象,它为叶对象和复合对象定义了一个方法,在本例中是 Employee,它具有 add(Employee e)
、remove(Employee e)
等方法以及常规方法,例如 getId()
、getName()
。
在我们的示例中,Employee 是一个抽象类,为大多数方法提供默认实现,它有两个具体的子类 Developer 和 Manager。
Manager 重写 directs()
方法以返回向他报告的 Employees 列表,而 developer 只返回一个空列表,这也是使用空对象模式避免 NullPointerException
的一个很好的例子。
下面是这个例子的完整代码
Employee.java
import java.util.List; public abstract class Employee { protected int id; protected String name; public Employee(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public String getName() { return name; } public void add(Employee e) { throw new UnsupportedOperationException(); } public void remove(Employee e) { throw new UnsupportedOperationException(); } public Employee getChild(int i) { throw new UnsupportedOperationException(); } public List<Employee> directs() { throw new UnsupportedOperationException(); } @Override public String toString() { return String.format("%s: %d", name, id); } }
Developer.java (Leaf object)
import java.util.Collections; import java.util.List; public class Developer extends Employee { public Developer(int id, String name) { super(id, name); } @Override public List<Employee> directs() { return Collections.EMPTY_LIST; } }
Manager.java
import java.util.ArrayList; import java.util.List; public class Manager extends Employee { private List<Employee> directs = new ArrayList<>(); public Manager(int id, String name) { super(id, name); } @Override public void add(Employee e) { directs.add(e); } @Override public void remove(Employee e) { directs.add(e); } @Override public Employee getChild(int i) { return directs.get(i); } @Override public List<Employee> directs() { return directs; } }
CompositePattern.java
import java.util.ArrayList; import java.util.List; public class CompositePatternTest { public static void main(String args[]) { Developer john = new Developer(101, "John"); Developer robin = new Developer(102, "Robin"); Developer peter = new Developer(103, "Peter"); Developer luke = new Developer(104, "Luke"); Developer amy = new Developer(105, "Amy"); Manager steve = new Manager(106, "Steve"); steve.add(john); steve.add(robin); steve.add(peter); Manager frank = new Manager(107, "Frank"); frank.add(luke); frank.add(amy); frank.add(steve); List<Employee> org = new ArrayList<>(); org.add(john); org.add(robin); org.add(peter); org.add(luke); org.add(amy); org.add(steve); org.add(frank); for (Employee e : org) { System.out.printf("%s manages %s %n", e.getName(), e.directs()); } } }
大家可以看到,在调用 directs()
方法之前,对员工列表进行操作的代码没有进行条件检查。 我们还可以使用此模式打印组织结构图,其中每个经理负责打印其记者,通过定义 receive()
方法将消息传达给每个员工,每个经理将进一步将消息传达给他的下属。
什么时候在 Java 中使用复合设计模式?
如果具有层次结构或树状结构,例如组织中的员工、家庭中的家庭成员、XML 文档中的节点等,我们应该考虑使用复合模式。
要找到复合设计模式的用法,要记住的另一个关键是使用 instanceof
运算符,如果我们正在接收一个对象,而不是直接调用它的方法,检查特定类型,那么 Composite 是一种统一处理它们的方法。
在这个例子中,如果我们需要在 Employee 上调用 directs()
方法,我们也可以通过检查每个员工 instanceof Manager
代码来实现。 复合模式允许我们以统一的方式处理叶对象和复合对象。
这是一个有用的模式,可以在很多情况下简化我们的代码。
这是复合设计模式的一个很好的 UML 图,它将帮助大家更好地理解这种模式。
这就是关于什么是 Java 中的复合设计模式的全部内容。 我们不仅学习了如何在 Java 中实现复合设计模式,还学习了何时使用复合模式以及复合模式的优缺点。 它是 Java 开发人员设计模式库中的一种使用模式。
正如我们所见,此模式的主要优点之一是代码简单易读,这是可能的,因为以类似的方式处理复合对象和节点对象。
同样的特性也是它最大的缺点,因为它允许客户端调用节点对象上的复合方法,这些方法不应该被调用或没有有效的行为。 与任何设计决策一样,如果复合模式的优势超过错误方法调用的风险,则必须权衡取舍。
相关文章
使用 Java 在 MongoDB 中生成 ObjectId
发布时间:2023/04/20 浏览次数:179 分类:MongoDB
-
本文将讨论 ObjectId 以及我们如何使用 Java 程序生成它。 为了使主题更简单,我们将看到一个带有解释的示例,以使主题更容易。
在 PHP 变量中存储 Div Id 并将其传递给 JavaScript
发布时间:2023/03/29 浏览次数:69 分类:PHP
-
本文教导将 div id 存储在 PHP 变量中并将其传递给 JavaScript 代码。
如何在 Java 中把日期转换为字符串
发布时间:2023/03/28 浏览次数:192 分类:Java
-
本篇文章介绍了如何在 Java 中把 java.util.Date 转换为字符串 String。