如何在迷宫生成求解程序中支持并绘制多种不同的求解算法
优化方案:采用绘制策略模式解耦绘制逻辑与JPanel实现
核心思路
将不同求解器的绘制逻辑、对应所需的参数全部封装到独立的绘制策略类中,JPanel仅依赖统一的绘制接口,无需感知不同求解器的参数差异,也不需要创建多份JPanel子类。
具体实现步骤
1. 定义统一绘制接口
首先抽象所有求解器绘制逻辑的公共行为,定义接口:
public interface MazeSolverDrawer { // 统一传入绘图上下文和基础迷宫对象,其余参数由实现类自行持有 void draw(Graphics g, Maze baseMaze); }
2. 每个求解器实现专属绘制策略
不同求解器的实现类自行存储所需的所有参数,实现接口的draw方法完成专属绘制逻辑:
// 求解器1的绘制实现 public class Solver1Drawer implements MazeSolverDrawer { // 存储求解器1绘制需要的所有个性化参数 private List<Point> visitedPath; private Queue<Point> pendingNodes; private int currentStep; // 构造方法传入所有需要的参数 public Solver1Drawer(List<Point> visitedPath, Queue<Point> pendingNodes, int currentStep) { this.visitedPath = visitedPath; this.pendingNodes = pendingNodes; this.currentStep = currentStep; } @Override public void draw(Graphics g, Maze baseMaze) { // 此处编写求解器1专属的子步骤绘制逻辑,参数均由当前类持有,可直接使用 } } // 求解器2的绘制实现,可自由定义需要的参数 public class Solver2Drawer implements MazeSolverDrawer { private Stack<Point> backtrackStack; private boolean[][] visitedMark; public Solver2Drawer(Stack<Point> backtrackStack, boolean[][] visitedMark) { this.backtrackStack = backtrackStack; this.visitedMark = visitedMark; } @Override public void draw(Graphics g, Maze baseMaze) { // 求解器2的绘制逻辑 } }
3. 简化JPanel实现
JPanel仅保留基础绘制逻辑和统一的绘制策略入口,不需要switch分支,也不需要存储不同求解器的参数:
public class MazePanel extends JPanel { private Maze maze; // 持有当前使用的绘制策略实例 private MazeSolverDrawer currentSolverDrawer; // 对外提供方法,切换求解器/更新求解状态时传入对应绘制策略即可 public void setCurrentSolverDrawer(MazeSolverDrawer drawer) { this.currentSolverDrawer = drawer; repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 绘制基础迷宫 drawMaze(g); // 存在绘制策略时调用其绘制方法 if (currentSolverDrawer != null) { currentSolverDrawer.draw(g, maze); } } private void drawMaze(Graphics g) { // 原有基础迷宫绘制逻辑 } }
扩展优化(Java 8+适用)
如果不想为每个求解器单独创建实现类,可直接用Lambda表达式实现MazeSolverDrawer接口,在求解器运行更新状态时直接传入绘制逻辑:
// Solver1运行过程中更新绘制状态时的调用示例 List<Point> currentVisited = ...; Queue<Point> currentPending = ...; int step = ...; mazePanel.setCurrentSolverDrawer((g, maze) -> { // 直接编写Solver1的绘制逻辑,外部的currentVisited等变量只要是final或等效final即可直接使用 });
方案优势
- 无需创建多份JPanel子类,全局仅需一份MazePanel实现
- 新增求解器时不需要修改原有JPanel代码,符合开闭原则
- 求解器的参数与绘制逻辑内聚在各自的实现类中,不会在JPanel中堆积冗余成员变量
- 完全符合Swing的绘制规范,所有绘制逻辑均在paintComponent中执行,性能更稳定
内容的提问来源于stack exchange,提问作者Szász Erik
相关产品推荐
相关产品推荐

