面试题答案
一键面试1. Java组合模式设计系统
- 定义抽象任务类(Component):
public abstract class Task { protected String name; protected Task parent; public Task(String name) { this.name = name; } public void setParent(Task parent) { this.parent = parent; } public Task getParent() { return parent; } public abstract void execute(); public abstract void addTask(Task task); public abstract void removeTask(Task task); public abstract Task getTask(int index); }
- 定义叶子任务类(Leaf):
public class LeafTask extends Task { public LeafTask(String name) { super(name); } @Override public void execute() { System.out.println("执行叶子任务: " + name); } @Override public void addTask(Task task) { throw new UnsupportedOperationException("叶子任务不能添加子任务"); } @Override public void removeTask(Task task) { throw new UnsupportedOperationException("叶子任务不能移除子任务"); } @Override public Task getTask(int index) { throw new UnsupportedOperationException("叶子任务没有子任务"); } }
- 定义组合任务类(Composite):
import java.util.ArrayList; import java.util.List; public class CompositeTask extends Task { private List<Task> children = new ArrayList<>(); public CompositeTask(String name) { super(name); } @Override public void execute() { System.out.println("执行组合任务: " + name); for (Task task : children) { task.execute(); } } @Override public void addTask(Task task) { task.setParent(this); children.add(task); } @Override public void removeTask(Task task) { children.remove(task); } @Override public Task getTask(int index) { return children.get(index); } }
2. 依赖关系处理
- 设计选择:
- 在
Task
类中添加一个List<Task>
类型的dependencies
字段,用于存储该任务所依赖的其他任务。 - 在执行任务前,先检查其依赖任务是否已完成。可以在
Task
类中添加一个isDependenciesMet()
方法,遍历dependencies
列表,检查每个依赖任务的执行状态。
public abstract class Task { // 其他代码... protected List<Task> dependencies = new ArrayList<>(); public void addDependency(Task task) { dependencies.add(task); } public boolean isDependenciesMet() { // 假设任务执行后有一个isExecuted标志 for (Task task : dependencies) { if (!task.isExecuted()) { return false; } } return true; } public abstract boolean isExecuted(); }
- 在
execute()
方法中,先调用isDependenciesMet()
方法,只有当依赖满足时才执行任务。
public class LeafTask extends Task { private boolean executed = false; // 其他代码... @Override public void execute() { if (isDependenciesMet()) { System.out.println("执行叶子任务: " + name); executed = true; } else { System.out.println("叶子任务 " + name + " 的依赖未满足,无法执行"); } } @Override public boolean isExecuted() { return executed; } }
public class CompositeTask extends Task { private boolean executed = false; // 其他代码... @Override public void execute() { if (isDependenciesMet()) { System.out.println("执行组合任务: " + name); for (Task task : children) { task.execute(); } executed = true; } else { System.out.println("组合任务 " + name + " 的依赖未满足,无法执行"); } } @Override public boolean isExecuted() { return executed; } }
- 在
- 权衡:
- 优点:这种方式直观简单,易于理解和实现,能够清晰地表达任务之间的依赖关系。
- 缺点:可能会导致任务间的耦合度增加,特别是在依赖关系复杂时,维护和修改依赖关系可能会变得困难。而且如果依赖任务的执行状态判断逻辑复杂,会使
isDependenciesMet()
方法变得臃肿。
3. 权限控制
- 设计选择:
- 在
Task
类中添加一个UserRole
类型的requiredRole
字段,用于表示执行该任务所需的用户角色。 - 在执行任务前,检查当前用户的角色是否满足任务的
requiredRole
。可以在Task
类中添加一个hasPermission(User user)
方法,根据用户的角色判断是否有权限执行任务。
public enum UserRole { ADMIN, USER, GUEST } public abstract class Task { // 其他代码... protected UserRole requiredRole; public Task(String name, UserRole requiredRole) { this.name = name; this.requiredRole = requiredRole; } public boolean hasPermission(User user) { return user.getRole().ordinal() >= requiredRole.ordinal(); } } public class User { private UserRole role; public User(UserRole role) { this.role = role; } public UserRole getRole() { return role; } }
- 在
execute()
方法中,先调用hasPermission(User user)
方法,只有当用户有权限时才执行任务。
public class LeafTask extends Task { // 其他代码... @Override public void execute(User user) { if (hasPermission(user)) { System.out.println("执行叶子任务: " + name); } else { System.out.println("用户 " + user.getRole() + " 没有权限执行叶子任务 " + name); } } }
public class CompositeTask extends Task { // 其他代码... @Override public void execute(User user) { if (hasPermission(user)) { System.out.println("执行组合任务: " + name); for (Task task : children) { task.execute(user); } } else { System.out.println("用户 " + user.getRole() + " 没有权限执行组合任务 " + name); } } }
- 在
- 权衡:
- 优点:将权限控制逻辑集中在
Task
类中,易于管理和维护。通过枚举来表示用户角色,使得权限判断逻辑清晰明了。 - 缺点:这种方式假设用户角色是一种简单的层次结构,对于复杂的权限模型(如基于资源的权限控制、多维度权限等)可能不太适用,扩展性有限。
- 优点:将权限控制逻辑集中在
4. 任务调度策略
- 设计选择:
- 定义一个
TaskScheduler
类,负责管理任务的调度。可以在TaskScheduler
类中维护一个任务队列,根据不同的调度策略将任务添加到队列中,并按策略执行任务。 - 例如,实现一个简单的先进先出(FIFO)调度策略:
import java.util.LinkedList; import java.util.Queue; public class TaskScheduler { private Queue<Task> taskQueue = new LinkedList<>(); public void addTask(Task task) { taskQueue.add(task); } public void executeTasks(User user) { while (!taskQueue.isEmpty()) { Task task = taskQueue.poll(); if (task.hasPermission(user) && task.isDependenciesMet()) { task.execute(user); } } } }
- 对于动态调度策略,可以在
Task
类中添加一个Priority
字段表示任务优先级,在TaskScheduler
类中根据优先级对任务队列进行排序。
public abstract class Task { // 其他代码... protected int priority; public Task(String name, UserRole requiredRole, int priority) { this.name = name; this.requiredRole = requiredRole; this.priority = priority; } public int getPriority() { return priority; } }
import java.util.PriorityQueue; import java.util.Queue; public class TaskScheduler { private Queue<Task> taskQueue = new PriorityQueue<>((t1, t2) -> t2.getPriority() - t1.getPriority()); public void addTask(Task task) { taskQueue.add(task); } public void executeTasks(User user) { while (!taskQueue.isEmpty()) { Task task = taskQueue.poll(); if (task.hasPermission(user) && task.isDependenciesMet()) { task.execute(user); } } } }
- 定义一个
- 权衡:
- 优点:将任务调度逻辑封装在
TaskScheduler
类中,使得系统的任务调度部分易于扩展和维护。通过不同的数据结构(如队列、优先队列)可以方便地实现不同的调度策略。 - 缺点:如果调度策略非常复杂,可能会导致
TaskScheduler
类变得庞大和复杂,需要进行良好的模块化设计来避免代码混乱。同时,动态调度策略可能会增加系统的运行时开销,例如优先队列的排序操作。
- 优点:将任务调度逻辑封装在