#java #design-patterns
Вопрос:
Я создал приложение, которое позволяет создавать экземпляры фигур, которые могут быть кругом, прямоугольником или чем угодно, и использовал метод сортировки (Пузырьковая сортировка) для сортировки шести фигур на основе интерфейсов.
Проблема в том, что я не знаком с шаблонами дизайна и с тем, какие шаблоны используются — я новичок, поэтому я следил за видео на YouTube и играл с ними, и это сработало.
У меня есть 1 основной класс, где у меня есть ОСНОВНОЙ :
public class Main {
public static void main(String[] args) {
JButton btnLoadShapes, btnSortShapes;
btnLoadShapes = new JButton("Load Shapes");
btnLoadShapes.setBounds(150, 10, 150, 30);
btnSortShapes = new JButton("Sort Shapes");
btnSortShapes.setBounds(310, 10, 150, 30);
JPanel panelShapes = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Shape shape = new Shape();
g2d.setColor(Color.RED);
Square s = shape.getS();
g2d.fillRect(s.getX(),s.getY(),s.getWidth(), s.getHeight());
g2d.setColor(Color.BLUE);
Circle c = shape.getC();
g2d.fillOval(c.getX(),c.getY(), c.getWidth(), c.getHeight());
g2d.setColor(new Color(131, 21, 1));
Rectangle r = shape.getR();
g2d.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
g2d.setColor(Color.PINK);
Circle C1 = shape.getC1();
g2d.fillOval(C1.getX(),C1.getY(), C1.getWidth(), C1.getHeight());
g2d.setColor(Color.green);
Square S1 = shape.getS1();
g2d.fillRect(S1.getX(),S1.getY(),S1.getWidth(), S1.getHeight());
g2d.setColor(Color.magenta);
Rectangle r2 = shape.getR2();
g2d.fillRect(r2.getX(),r2.getY(),r2.getWidth(), r2.getHeight());
}
};
panelShapes.setBounds(10, 50, 560, 500);
panelShapes.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panelShapes.setVisible(false);
btnLoadShapes.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
panelShapes.setVisible(true);
}
});
и я создал 3 разных класса: Круг, прямоугольник и Квадрат, из которых я вызываю rectangle = shape.getC();
Например
, круг публичных занятий {
частное int x, y, ширина, высота;
public Circle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Теперь, наконец, я создал еще 2 класса под названием «Форма и сортировка», где в форме я ввел общедоступную форму s = новый квадрат с размерами и заданными получателями и установщиками, и, наконец, я использовал технику сортировки.
Может ли кто-нибудь помочь мне понять, какие шаблоны проектирования здесь используются? ( Я предполагаю, что используется фабричный метод = так как я определил main (* интерфейс) и создал подклассы ( Фигуры прямоугольник круг) для создания экземпляра.
Извините, если я звучу неуместно — я просто пытаюсь понять и изучить это.
Комментарии:
1. Код вырван из контекста, но, основываясь на
public class Circle {
том , что я бы не сказал, что вы используете фактический шаблон «фабрики», поскольку «фабрика» вернет базовое представление, детали реализации не имеют значения. Как aCar
, но фабрика могла бы производить aFord
илиTesla
, но они все еще являются примеромCar
2. Я обновил коды, дайте мне знать, если это поможет
3. Кажется очень странным писать какой-то код и предполагать, что это шаблон. Во-первых, вам не нужно использовать какой-либо шаблон для написания кода. Во-вторых, если вы хотите узнать о шаблонах, то почему бы не изучить шаблоны? Существует множество книг, видео, блогов и т. Д. где вам не нужно гадать. В-третьих, шаблоны не являются хорошим способом изучения программирования, ИМО. Они не являются темой для начинающих/вводной. Знание того, как кодировать без шаблонов, более ценно, чем знание шаблонов. Паттерны вторичны.
Ответ №1:
«Фабрика» создает «что-то», в этом контексте важно то, что вам все равно, «как» оно создано, только то, что оно соответствует указанному типу.
Например, у вас есть ShapeFactory
устройство, которое может создавать различные формы, вам все равно, «как» эти формы определены или реализованы, только то, что они соответствуют понятию «форма».
Итак, давайте начнем с базовой концепции…
public interface Shape {
public void paint(Graphics2D g2d);
}
Это просто определяет базовую концепцию и утверждает, что ее можно нарисовать.
Далее, нам нужно что-то для создания этих фигур…
public class ShapeFactory {
enum ShapeType {
CIRCLE, RECTANGE, SQUARE;
}
public static Shape create(ShapeType type, int x, int y, int width, int height, Color storkeColor, Color fillColor) {
return null;
}
}
Ладно, в нынешнем виде это довольно скучно, он вернется только null
сейчас, но это дает нам базовый контракт.
«Пожалуйста, фабрика, создайте мне фигуру указанного типа, в указанных пределах, с указанными цветами»
Теперь, как я уже сказал, реализация не имеет значения для вызывающего, и у нас может быть динамическая фабрика, которая может делегировать создание другим фабрикам, которые могут создавать формы по-разному в зависимости от широкого набора потребностей … но это забегая вперед.
Давайте займемся созданием некоторых реальных фигур…
public abstract class AbstractShape implements Shape {
private int x;
private int y;
private int width;
private int height;
private Color storkeColor;
private Color fillColor;
public AbstractShape(Color storkeColor, Color fillColor) {
this.storkeColor = storkeColor;
this.fillColor = fillColor;
}
public AbstractShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
this(storkeColor, fillColor);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
protected void setX(int x) {
this.x = x;
}
protected void setY(int y) {
this.y = y;
}
protected void setWidth(int width) {
this.width = width;
}
protected void setHeight(int height) {
this.height = height;
}
public Color getStorkeColor() {
return storkeColor;
}
public Color getFillColor() {
return fillColor;
}
@Override
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
Color storkeColor = getStorkeColor();
Color fillColor = getFillColor();
if (fillColor != null) {
g.setColor(fillColor);
paintFilled(g);
}
if (storkeColor != null) {
g.setColor(storkeColor);
paintStroked(g);
}
g.dispose();
}
abstract protected void paintFilled(Graphics2D g2d);
abstract protected void paintStroked(Graphics2D g2d);
}
public class CircleShape extends AbstractShape {
public CircleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x ((width - size) / 2);
y = y ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
@Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillOval(getX(), getY(), getWidth(), getHeight());
}
@Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawOval(getX(), getY(), getWidth(), getHeight());
}
}
public class SquareShape extends AbstractShape {
public SquareShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x ((width - size) / 2);
y = y ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
@Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
@Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
public class RectagleShape extends AbstractShape {
public RectagleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(x, y, width, height, storkeColor, fillColor);
}
@Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
@Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
Мне всегда нравится abstract
, когда класс несет в себе «общую» функциональность и помогает немного упростить жизнь.
Здесь важно отметить , что оба CircleShape
и SquareShape
, по своей природе, ну, квадратные (они имеют одинаковую ширину и высоту). Итак, в этой реализации я определяю их так, чтобы они укладывались в середину указанных границ — это деталь «реализации».
«Но разве не это я делаю для тебя?» ты спрашиваешь. Ну, нет, не совсем так. Например , когда вы вызываете shape.getS()
, он возвращает конкретный класс, который, как я предполагаю, обладает теми же свойствами, что и последний созданный им объект, в противном случае он будет перемещаться повсюду.
Вместо этого я позволяю вам определить свойства, которые вы хотите, чтобы форма имела, а затем создать ее.
Хочешь торт? Конечно, передайте мне ингредиенты, и я приготовлю вам торт, вы все равно получите торт, но в зависимости от ингредиентов это другой «тип» торта.
Итак, основываясь на вышесказанном, мы могли бы сделать что-то вроде…
public class TestPane extends JPanel {
private List<Shape> shapes = new ArrayList<>(25);
public TestPane() {
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.CIRCLE, 10, 10, 200, 100, Color.RED, Color.BLUE));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.RECTANGE, 10, 120, 200, 100, Color.BLUE, Color.GREEN));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.SQUARE, 10, 240, 200, 100, Color.GREEN, Color.YELLOW));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(220, 350);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape shape : shapes) {
shape.paint(g2d);
}
g2d.dispose();
}
}
Я мог бы сделать ShapeFactory
это с помощью преданных createCircle
createRectangle
и createSquare
методов , я мог бы вернуть их interfaces
Circle
, Square
и Rectangle
(и я бы основал их , Shape
потому что я такой), и это все равно было бы фабрикой.
Одна из вещей, которую следует иметь в виду, заключается в том, что «фабрика» должна быть независимой от реализации. Я должен был бы использовать фабрики «разных» форм для получения разных эффектов, но в конце концов они все равно будут генерировать Shape
s
Помните, фабрика возьмет что-то и создаст что-то из этого.