如何支持和绘制多种算法
How to support and paint multiple algorithms
我一直在研究迷宫 generator/solver 程序。它工作得很好,但我在重构代码时遇到了一个问题。
基本上,我过去常常调用直接从另一个 class 绘制解决迷宫过程的方法,而不是调用 paintComponent 方法(或者更确切地说是 repaint 方法)。显然这不是一个好的做法,在性能方面也不令人满意,我正在努力解决这个问题。
问题是,要绘制解决方案的子步骤,不同的求解器算法需要不同类型和数量的参数。
我可以将它们存储在 class 中,然后调用 paintComponent 方法,在该方法中我调用使用上述参数绘制子步骤的方法。
不幸的是,这意味着我必须创建一堆扩展 JPanel 的其他 classes,这样我就可以存储必要的集合和变量,这样我就可以绘制一个特定的解决方案。
有没有更好的方法来解决这个问题,还是我应该放弃并按照我提到的方式去做?
所以我想做的是:
@Override
public void paintComponent(Graphics g){
super(g);
drawMaze(g);
switch(solverType) //Based on what solver is assigned to the maze it calls the proper method
{
case solver1:
solver1Drawer(g, additional arguments);
break;
case solver2:
solver2Drawer(g, different kind, and number of arguments);
break;
//Other cases, with other method calls
}
}
有很多方法可以构建可以接受不同求解器和视图的此类应用程序。我将尝试演示一个非常基本的精简版,以使其尽可能简单。
为此,我们将使用求解器来计算特定形状的周长并绘制解决方案。
首先,我们将定义一些接口,稍后应该会更清楚地使用这些接口:
interface Model{
boolean solve();
int solution();
boolean isSolved();
}
interface View{
void draw(Graphics g);
}
interface Solver {
Model getModel();
View getView();
}
使用这些接口,我们将定义M模型、V视图和C控制器支持计算正方形的周长。
该模型封装了信息(属性和状态)和逻辑:
class SquarePrimeterModel implements Model{
private final int edgeLength;
private int perimeter;
private boolean isSolved = false;
public SquarePrimeterModel(int edgeLength) {
this.edgeLength = edgeLength;
}
@Override
public boolean solve() {
perimeter = 4 * edgeLength;
isSolved = true;
return true;
}
@Override
public int solution() {
return perimeter;
}
@Override
public boolean isSolved() {
return isSolved;
}
//edgeLength is a unique property for this model
public int getEdgeLength() {
return edgeLength;
}
}
视图的职责,顾名思义生成视图:
class SquarePrimeterView implements View{
private final static int xOffset = 50, yOffset = 50, GAP = 20;
private final SquarePrimeterModel model;
public SquarePrimeterView(SquarePrimeterModel model) {
this.model = model;
}
@Override
public void draw(Graphics g) {
if(model.isSolved()){
g.drawRect(xOffset, yOffset, model.getEdgeLength(), model.getEdgeLength());
String text = "Edge =" + model.getEdgeLength() + " Perimiter ="+ model.solution();
int yPosition = yOffset + model.getEdgeLength()+ GAP;
g.drawString(text, xOffset, yPosition);
}
}
}
控制器构建、配置和管理模型和视图:
class SquarePrimeterController implements Solver{
private final SquarePrimeterModel model;
private final View view;
public SquarePrimeterController(int edgeLength) {
model = new SquarePrimeterModel(edgeLength);
view = new SquarePrimeterView(model);
}
@Override
public Model getModel() {
return model;
}
@Override
public View getView() {
return view;
}
}
如果我们需要另一个求解器,例如计算三角形周长的求解器,我们只需编写 TriangelPrimeterController、TriangelPrimeterModel 和 TriangelPrimeterView,非常类似于 SquarePrimeter 类.
我们需要的最后一段代码是使用 SquarePrimeterController
:
的应用程序
public class SwingMVCSolveController {
public SwingMVCSolveController() {
Solver solver = new SquarePrimeterController(150);//todo: select solver by gui
solver.getModel().solve(); //todo start solve by gui
new MainView(solver.getView());
}
public static void main(String[] args) {
new SwingMVCSolveController();
}
}
class MainView extends JPanel {
private static final Dimension size = new Dimension(400, 400);
private final View solverView;
public MainView(View view) {
solverView = view;
createAndShowGui();
}
private void createAndShowGui() {
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add (this);
frame.pack();
frame.setVisible (true);
}
@Override
public Dimension getPreferredSize() {
return size;
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
solverView.draw(g);
}
}
显然 Solver solver = new SquarePrimeterController(150);
可以更改为 Solver solver = new TrianglePrimeterController(150);
或 Solver
的任何其他实现。
完整的可运行代码可用here
我一直在研究迷宫 generator/solver 程序。它工作得很好,但我在重构代码时遇到了一个问题。
基本上,我过去常常调用直接从另一个 class 绘制解决迷宫过程的方法,而不是调用 paintComponent 方法(或者更确切地说是 repaint 方法)。显然这不是一个好的做法,在性能方面也不令人满意,我正在努力解决这个问题。
问题是,要绘制解决方案的子步骤,不同的求解器算法需要不同类型和数量的参数。 我可以将它们存储在 class 中,然后调用 paintComponent 方法,在该方法中我调用使用上述参数绘制子步骤的方法。
不幸的是,这意味着我必须创建一堆扩展 JPanel 的其他 classes,这样我就可以存储必要的集合和变量,这样我就可以绘制一个特定的解决方案。
有没有更好的方法来解决这个问题,还是我应该放弃并按照我提到的方式去做?
所以我想做的是:
@Override
public void paintComponent(Graphics g){
super(g);
drawMaze(g);
switch(solverType) //Based on what solver is assigned to the maze it calls the proper method
{
case solver1:
solver1Drawer(g, additional arguments);
break;
case solver2:
solver2Drawer(g, different kind, and number of arguments);
break;
//Other cases, with other method calls
}
}
有很多方法可以构建可以接受不同求解器和视图的此类应用程序。我将尝试演示一个非常基本的精简版,以使其尽可能简单。
为此,我们将使用求解器来计算特定形状的周长并绘制解决方案。
首先,我们将定义一些接口,稍后应该会更清楚地使用这些接口:
interface Model{
boolean solve();
int solution();
boolean isSolved();
}
interface View{
void draw(Graphics g);
}
interface Solver {
Model getModel();
View getView();
}
使用这些接口,我们将定义M模型、V视图和C控制器支持计算正方形的周长。
该模型封装了信息(属性和状态)和逻辑:
class SquarePrimeterModel implements Model{
private final int edgeLength;
private int perimeter;
private boolean isSolved = false;
public SquarePrimeterModel(int edgeLength) {
this.edgeLength = edgeLength;
}
@Override
public boolean solve() {
perimeter = 4 * edgeLength;
isSolved = true;
return true;
}
@Override
public int solution() {
return perimeter;
}
@Override
public boolean isSolved() {
return isSolved;
}
//edgeLength is a unique property for this model
public int getEdgeLength() {
return edgeLength;
}
}
视图的职责,顾名思义生成视图:
class SquarePrimeterView implements View{
private final static int xOffset = 50, yOffset = 50, GAP = 20;
private final SquarePrimeterModel model;
public SquarePrimeterView(SquarePrimeterModel model) {
this.model = model;
}
@Override
public void draw(Graphics g) {
if(model.isSolved()){
g.drawRect(xOffset, yOffset, model.getEdgeLength(), model.getEdgeLength());
String text = "Edge =" + model.getEdgeLength() + " Perimiter ="+ model.solution();
int yPosition = yOffset + model.getEdgeLength()+ GAP;
g.drawString(text, xOffset, yPosition);
}
}
}
控制器构建、配置和管理模型和视图:
class SquarePrimeterController implements Solver{
private final SquarePrimeterModel model;
private final View view;
public SquarePrimeterController(int edgeLength) {
model = new SquarePrimeterModel(edgeLength);
view = new SquarePrimeterView(model);
}
@Override
public Model getModel() {
return model;
}
@Override
public View getView() {
return view;
}
}
如果我们需要另一个求解器,例如计算三角形周长的求解器,我们只需编写 TriangelPrimeterController、TriangelPrimeterModel 和 TriangelPrimeterView,非常类似于 SquarePrimeter 类.
我们需要的最后一段代码是使用 SquarePrimeterController
:
public class SwingMVCSolveController {
public SwingMVCSolveController() {
Solver solver = new SquarePrimeterController(150);//todo: select solver by gui
solver.getModel().solve(); //todo start solve by gui
new MainView(solver.getView());
}
public static void main(String[] args) {
new SwingMVCSolveController();
}
}
class MainView extends JPanel {
private static final Dimension size = new Dimension(400, 400);
private final View solverView;
public MainView(View view) {
solverView = view;
createAndShowGui();
}
private void createAndShowGui() {
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add (this);
frame.pack();
frame.setVisible (true);
}
@Override
public Dimension getPreferredSize() {
return size;
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
solverView.draw(g);
}
}
显然 Solver solver = new SquarePrimeterController(150);
可以更改为 Solver solver = new TrianglePrimeterController(150);
或 Solver
的任何其他实现。
完整的可运行代码可用here