创建表示多边形的类,而不是存储在阵列中



我被赋予了改进一段代码的任务。该代码用于绘制不同的多边形。初始代码有一个构造函数,它把多边形的名称加在一起;三角形"正方形";以及";矩形";到ArrayList。另一个ArrayList包含每个多边形的中心点。我已经被暗示,为每个多边形创建一个类将改进代码,因为它早在编译状态下就可以防止错误,比如用户会键入错误的多边形名称。我对编码还很陌生,所以我真的不知道如何在实际中实现它。有人能举个例子说明这样一个班级会是什么样子吗?

您可以为多边形类型创建一个Enum,如下所示:

public enum PolygonType{
TRIANGLE, SQUARE, RECTANGLE, PENTAGON, HEXAGON
}

创建一个类,表示多边形的单个实例:

public class Polygon {
private final PolygonType type;

//Use whatever Point class you use now here
private final Point2D center;
public Polygon(PolygonType type, Point2D center) {
this.type = type;
this.center = center;
}
public PolygonType getType() {
return type;
}
public Point2D getCenter() {
return center;
}
}

然后简单地有一个List<Polygon>

如果不想对类型使用枚举,也可以只存储边数,或者将类型存储为String。我更喜欢使用enum,因为不能使用错误的值。

如果需要,还可以通过添加字段和构造函数(构造函数应该是private(来为枚举提供额外信息,例如边数:

public enum PolygonType {
TRIANGLE(3), SQUARE(4), RECTANGLE(4);
public final int sides;
private PolygonType(int sides) {this.sides = sides;}
} 

您可以创建一个ShapeType来识别形状。

然后可以创建一个代表Shapeabstract类,然后通过创建各种多边形和几何形状来扩展它。

如果所有形状都有一个类型、位置(原点(和大小,则可以通过switch语句处理该类型来创建该类型的形状。


演示

下面的示例生成10-50个随机颜色的随机形状,大小为画布宽度的5%-10%,并将它们放置在画布中心最大距离的三分之一以内。

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Point2D;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class App implements Runnable {
private enum ShapeType {
CIRCLE, HEXAGON, PENTAGON, RECTANGLE, SQUARE, TRIANGLE;
}
private static abstract class Shape {
private ShapeType type;
private Point2D origin;
private Color color;
protected boolean dirty;
protected Map<String, Object> attributes;
public ShapeType getType() {
return type;
}
public Point2D getOrigin() {
return origin;
}
public void setOrigin(Point2D origin) {
this.origin = origin;
this.dirty = true;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
this.dirty = true;
}
public Map<String, Object> getAttributes() {
return attributes;
}
public Shape(ShapeType type, Point2D origin, Color color) {
this.type = type;
this.origin = origin;
this.color = color;
this.attributes = new HashMap<>();
this.dirty = true;
}
protected void attr(String attribute, Object value) {
this.attributes.put(attribute, value);
}
protected Object attr(String attribute) {
return this.attributes.get(attribute);
}
protected void recalculate() {
syncAttributes();
this.dirty = false;
}
protected void syncAttributes() {
int rgb = (this.getColor().getRGB() << 8) >>> 8;
attr("color", String.format("#%06X", rgb));
attr("x", getOrigin().getX());
attr("y", getOrigin().getY());
}
public abstract void draw(Graphics2D g2d);
}
private static class Rectangle extends Shape {
private int x;
private int y;
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
this.dirty = true;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
this.dirty = true;
}
public Rectangle(Point2D origin, Color color, int width, int height) {
super(ShapeType.RECTANGLE, origin, color);
this.width = width;
this.height = height;
}
@Override
protected void syncAttributes() {
super.syncAttributes();
attr("width", this.getWidth());
attr("height", this.getHeight());
}
@Override
protected void recalculate() {
this.x = (int) getOrigin().getX() - this.width / 2;
this.y = (int) getOrigin().getY() - this.height / 2;
super.recalculate();
}
@Override
public void draw(Graphics2D g2d) {
g2d.setColor(this.getColor());
g2d.fillRect(this.x, this.y, this.width, this.height);
}
}
private static class Square extends Shape {
private Rectangle rectangle;
@Override
public Color getColor() {
return rectangle.getColor();
}
@Override
public void setColor(Color color) {
rectangle.setColor(color);
this.dirty = true;
}
@Override
public Point2D getOrigin() {
return rectangle.getOrigin();
}
@Override
public void setOrigin(Point2D origin) {
rectangle.setOrigin(origin);
this.dirty = true;
}
public int getSize() {
return rectangle.getWidth();
}
public void setSize(int size) {
rectangle.setWidth(size);
rectangle.setHeight(size);
}
@Override
public Map<String, Object> getAttributes() {
return rectangle.getAttributes();
}
public Square(Point2D origin, Color color, int size) {
super(ShapeType.SQUARE, null, null);
this.rectangle = new Rectangle(origin, color, size, size);
}
@Override
protected void syncAttributes() {
super.syncAttributes();
attr("size", this.getSize());
}
@Override
protected void recalculate() {
this.rectangle.recalculate();
}
@Override
public void draw(Graphics2D g2d) {
this.rectangle.draw(g2d);
}
}
private static abstract class Polygon2D extends Shape {
private int sides;
private int radius;
private Polygon polygon;
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
this.dirty = true;
}
public Polygon2D(ShapeType type, int sides, Point2D origin, Color color, int radius) {
super(type, origin, color);
this.sides = sides;
this.radius = radius;
this.polygon = new Polygon();
}
@Override
protected void syncAttributes() {
super.syncAttributes();
List<Point2D> points = new ArrayList<>();
for (int i = 0; i < this.polygon.npoints; i++) {
points.add(new Point2D.Float(this.polygon.xpoints[i], this.polygon.ypoints[i]));
}
this.attr("radius", this.getRadius());
this.attr("points", points);
}
@Override
public void recalculate() {
this.polygon.reset();
double angle = Math.PI * 2 / this.sides;
double start = -Math.PI / 2;
for (int i = 0; i < this.sides; i++) {
double x = getOrigin().getX() + this.radius * Math.cos(start + i * angle);
double y = getOrigin().getY() + this.radius * Math.sin(start + i * angle);
this.polygon.addPoint((int) x, (int) y);
}
super.recalculate();
}
@Override
public void draw(Graphics2D g2d) {
g2d.setColor(this.getColor());
g2d.fillPolygon(this.polygon);
}
}
private static class Triangle extends Polygon2D {
public Triangle(Point2D origin, Color color, int radius) {
super(ShapeType.TRIANGLE, 3, origin, color, radius);
}
}
private static class Pentagon extends Polygon2D {
public Pentagon(Point2D origin, Color color, int radius) {
super(ShapeType.PENTAGON, 5, origin, color, radius);
}
}
private static class Hexagon extends Polygon2D {
public Hexagon(Point2D origin, Color color, int radius) {
super(ShapeType.HEXAGON, 6, origin, color, radius);
}
}
private static class Circle extends Shape {
private int radius;
private int x;
private int y;
private int width;
private int height;
public Circle(Point2D origin, Color color, int radius) {
super(ShapeType.CIRCLE, origin, color);
this.radius = radius;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
this.dirty = true;
}
@Override
protected void syncAttributes() {
super.syncAttributes();
attr("radius", this.getRadius());
}
@Override
protected void recalculate() {
this.x = (int) (this.getOrigin().getX() - this.getRadius());
this.y = (int) (this.getOrigin().getY() - this.getRadius());
this.width = this.getRadius() * 2;
this.height = this.width;
super.recalculate();
}
@Override
public void draw(Graphics2D g2d) {
g2d.setColor(this.getColor());
g2d.fillOval(this.x, this.y, this.width, this.height);
}
}
private static class Canvas extends JPanel {
private List<Shape> shapes;
public Canvas() {
super();
this.shapes = new ArrayList<>();
}
public void addShape(Shape shape) {
this.shapes.add(shape);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0x111111));
g.fillRect(0, 0, this.getWidth(), this.getHeight());
Graphics2D g2d = (Graphics2D) g;
for (Shape shape : this.shapes) {
if (shape.dirty) {
shape.recalculate();
}
shape.draw(g2d);
System.out.printf("Drawing %s %s%n", shape.getType(), JsonUtil.toJson(shape.getAttributes()));
}
}
}
private static class RandomUtil {
private static final Random rand = new Random(System.currentTimeMillis());
public static int randRange(int min, int max) {
return rand.nextInt(max + 1 - min) + min;
}
public static float randFloat() {
return rand.nextFloat();
}
public static <T> T randItem(T[] arr) {
return arr[rand.nextInt(arr.length)];
}
}
private static class JsonUtil {
public static String toJson(Map<String, Object> map) {
return String.format("{%s}", map.entrySet().stream()
.map(entry -> formatEntry(entry))
.collect(Collectors.joining(",")));
}
private static String formatValue(Object rawValue) {
String value = String.valueOf(rawValue);
if (rawValue instanceof String) {
value = String.format(""%s"", value);
} else if (rawValue instanceof List) {
value = String.format("[%s]", ((List) rawValue).stream()
.map(val -> formatValue(val))
.collect(Collectors.joining(",")));
} else if (rawValue instanceof Point2D) {
Point2D point = (Point2D) rawValue;
value = String.format("{"x":%.2f,"y":%.2f}", point.getX(), point.getY());
}
return value;
}
private static String formatEntry(Map.Entry entry) {
return String.format(""%s":%s", entry.getKey(), formatValue(entry.getValue()));
}
}
private static class ShapeUtil {
public static Shape randomShape(Dimension bounds) {
ShapeType type = RandomUtil.randItem(ShapeType.values());
Color color = Color.getHSBColor(RandomUtil.randFloat(), 0.667f, 1.0f);
int centerX = bounds.width / 2;
int centerY = bounds.height / 2;
int offX = bounds.width / 3;
int offY = bounds.height / 3;
int size = RandomUtil.randRange(bounds.width / 20, bounds.width / 10);
int x = RandomUtil.randRange(centerX - offX, centerX + offX);
int y = RandomUtil.randRange(centerY - offY, centerY + offY);
Point2D origin = new Point2D.Float(x, y);
return createShape(type, origin, color, size);
}
public static Shape createShape(ShapeType type, Point2D origin, Color color, int size) {
switch (type) {
case CIRCLE:
return new Circle(origin, color, size / 2);
case HEXAGON:
return new Hexagon(origin, color, size / 2);
case PENTAGON:
return new Pentagon(origin, color, size / 2);
case RECTANGLE:
case SQUARE:
return new Square(origin, color, size);
case TRIANGLE:
return new Triangle(origin, color, size);
default:
return null;
}
}
}
private String name;
private int width;
private int height;
private JFrame frame;
public App(String name, int width, int height) {
this.name = name;
this.width = width;
this.height = height;
}
protected void initialize() {
this.frame = new JFrame(this.name);
Canvas canvas = new Canvas();
Dimension bounds = new Dimension(this.width, this.height);
int shapeCount = RandomUtil.randRange(10, 50);
canvas.setPreferredSize(bounds);
for (int i = 0; i < shapeCount; i++) {
canvas.addShape(ShapeUtil.randomShape(bounds));
}
this.frame.setContentPane(canvas);
}
protected void finalize() {
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
@Override
public void run() {
initialize();
finalize();
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new App("Random Shapes", 400, 300));
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}

最新更新