Post

⛓️ Java Design-Pattern XXβ…’ - Command

⛓️ Java Design-Pattern XXβ…’ - Command

πŸ“— γ€ŽJAVA μ–Έμ–΄λ‘œ λ°°μš°λŠ” λ””μžμΈ νŒ¨ν„΄ : μ‰½κ²Œ λ°°μš°λŠ” GoF의 23κ°€μ§€ λ””μžμΈ νŒ¨ν„΄γ€λ₯Ό 읽고 μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€.

Command νŒ¨ν„΄μ΄λž€?

  • ν΄λž˜μŠ€λŠ” 자기 μžμ‹ μ΄λ‚˜ λ‹€λ₯Έ 클래슀의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ 일을 μ²˜λ¦¬ν•œλ‹€.
  • λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ κ²°κ³ΌλŠ” 객체에 λ°˜μ˜λ˜μ§€λ§Œ, μΌν•œ 이λ ₯은 어디에도 남지 μ•ŠλŠ”λ‹€.
  • 이럴 λ•Œ λͺ…령을 ν‘œν˜„ν•˜λŠ” ν΄λž˜μŠ€κ°€ 있으면 νŽΈλ¦¬ν•˜λ‹€.
  • μ²˜λ¦¬ν•˜κ³  싢은 일을 λ©”μ„œλ“œ ν˜ΈμΆœμ΄λΌλŠ” 동적인 처리둜 ν‘œν˜„ν•˜μ§€ μ•Šκ³ , λͺ…령을 λ‚˜νƒ€λ‚΄λŠ” 클래슀의 μΈμŠ€ν„΄μŠ€λΌλŠ” ν•˜λ‚˜μ˜ 객체둜 ν‘œν˜„ν•  수 μžˆλ‹€.
  • 이λ ₯을 κ΄€λ¦¬ν•˜κ³  싢을 λ•ŒλŠ” ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€μ˜ 집합을 κ΄€λ¦¬ν•˜λ©΄ λœλ‹€.
  • λͺ…λ Ήμ˜ 집합을 μ €μž₯해두면 같은 λͺ…령을 μž¬μ‹€ν–‰ν•  μˆ˜λ„ 있고, μ—¬λŸ¬ λͺ…령을 λͺ¨μ•„μ„œ μƒˆλ‘œμš΄ λͺ…λ ΉμœΌλ‘œ μž¬μ΄μš©ν•  μˆ˜λ„ μžˆλ‹€.
  • λ””μžμΈ νŒ¨ν„΄μ—μ„œλŠ” μ΄λŸ¬ν•œ λͺ…령에 CommandλΌλŠ” 이름을 λΆ™μ˜€μœΌλ©°, Event라고 λΆˆλ¦¬λŠ” κ²½μš°λ„ μžˆλ‹€.
  • κ°€λ Ή 마우슀 ν΄λ¦­μ΄λ‚˜ ν‚€ μž…λ ₯ λ“±μ˜ μ΄λ²€νŠΈκ°€ 일어났을 λ•Œ κ·Έ 사건을 일단 μΈμŠ€ν„΄μŠ€λΌλŠ” 객체둜 λ§Œλ“€μ–΄ 두고, λ°œμƒ μˆœμ„œλŒ€λ‘œ λŒ€κΈ° 행렬에 λ‚˜μ—΄ν•œλ‹€.
  • 그리고 λ‚˜μ—΄λœ 이벀트λ₯Ό μˆœμ„œλŒ€λ‘œ μ²˜λ¦¬ν•΄ λ‚˜κ°„λ‹€.

예제 ν”„λ‘œκ·Έλž¨

  • λ‹€μŒμ€ κ°„λ‹¨ν•œ κ·Έλ¦Ό 그리기 μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό 주제둜 ν•œ 예제 ν”„λ‘œκ·Έλž¨μ΄λ‹€.
  • 마우슀λ₯Ό λ“œλž˜κ·Έν•˜λ©΄ 빨간색 점으둜 된 선이 κ·Έλ €μ§€κ³ , [clear] λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ λͺ¨λ“  점이 사라진닀.
  • μ‚¬μš©μžκ°€ 마우슀λ₯Ό λ“œλž˜κ·Έν•  λ•Œλ§ˆλ‹€ β€˜μ΄ μœ„μΉ˜μ— 점을 κ·Έλ¦¬μ‹œμ˜€β€™λΌλŠ” λͺ…령이 DrawCommand 클래슀의 μΈμŠ€ν„΄μŠ€λ‘œ μƒμ„±λœλ‹€.

Command μΈν„°νŽ˜μ΄μŠ€

1
2
3
4
5
package command;

public interface Command {
	public abstract void execute();
}
  • λͺ…령을 λ‚˜νƒ€λ‚Έλ‹€.
  • execute() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œ ꡬ체적으둜 μ–΄λ–€ 일이 일어날 μ§€λŠ” ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€κ°€ κ²°μ •ν•œλ‹€.

MacroCommand 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package command;

import java.util.ArrayDeque;
import java.util.Deque;

public class MacroCommand implements Command {
	/* λͺ…λ Ήμ˜ λ°°μ—΄ */
	private Deque<Command> commands = new ArrayDeque<>();
	
	/* μ‹€ν–‰ */
	@Override
	public void execute() {
		for (Command cmd: commands) {
			cmd.execute();
		}
	}
	
	/* μΆ”κ°€ */
	public void append(Command cmd) {
		if (cmd == this) {
			throw new IllegalArgumentException("infinite loop caused by append");
		}
		
		commands.push(cmd);
	}
	
	/* λ§ˆμ§€λ§‰ λͺ…령을 μ‚­μ œ */
	public void undo() {
		if (!commands.isEmpty()) {
			commands.pop();
		}
	}
	
	/* μ „λΆ€ μ‚­μ œ */
	public void clear() {
		commands.clear();
	}
}
  • 볡수의 λͺ…령을 λͺ¨μ€ λͺ…령을 λ‚˜νƒ€λ‚΄λ©°, Command μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€.
  • commands ν•„λ“œλŠ” java.util.Deque μΈν„°νŽ˜μ΄μŠ€λ‘œ μ—¬λŸ¬ Command의 μΈμŠ€ν„΄μŠ€λ₯Ό λͺ¨μ•„ 두기 μœ„ν•œ 것이닀.
  • λ˜ν•œ Command μΈν„°νŽ˜μ΄μŠ€μ˜ execute() λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³  μžˆλŠ”λ°, 각 μΈμŠ€ν„΄μŠ€μ˜ execute() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ³  μžˆλ‹€.
  • μ–΄μ©Œλ©΄ 이 for λ£¨ν”„μ—μ„œ μ‹€ν–‰ν•˜λ €λŠ” Commandκ°€ μƒˆλ‘œμš΄ MacroCommand의 μΈμŠ€ν„΄μŠ€μΌ μˆ˜λ„ μžˆλ‹€.
  • 그런 κ²½μš°μ—λ„ λ‹€μ‹œ κ·Έ μΈμŠ€ν„΄μŠ€μ˜ execute() λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜λ―€λ‘œ κ²°κ΅­ λͺ¨λ“  Commandκ°€ μ‹€ν–‰λœλ‹€.
  • append() λ©”μ„œλ“œλŠ” MacroCommand μΈμŠ€ν„΄μŠ€μ— μƒˆλ‘œμš΄ Command의 μΈμŠ€ν„΄μŠ€λ₯Ό μΆ”κ°€ν•˜λŠ” λ©”μ„œλ“œμ΄λ‹€.
  • μΆ”κ°€λ˜λŠ” Command의 μΈμŠ€ν„΄μŠ€λŠ” λ‹€λ₯Έ MacroCommand μΈμŠ€ν„΄μŠ€μΌ μˆ˜λ„ μžˆλŠ”λ°, μ‹€μˆ˜λ‘œ 자기 μžμ‹ μ„ push() 해버리면 execute() λ©”μ„œλ“œκ°€ μ˜μ›νžˆ λλ‚˜μ§€ μ•ŠμœΌλ―€λ‘œ 인수λ₯Ό μ²΄ν¬ν•œλ‹€.
  • undo() λ©”μ„œλ“œλŠ” λ§ˆμ§€λ§‰μœΌλ‘œ μΆ”κ°€ν•œ Command μΈμŠ€ν„΄μŠ€λ₯Ό μ œκ±°ν•œλ‹€.
  • clear() λ©”μ„œλ“œλŠ” λͺ¨λ“  λͺ…령을 μ‚­μ œν•œλ‹€.

DrawCommand 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package drawer;

import command.Command;
import java.awt.Point;

public class DrawCommand implements Command {
	/* κ·Έλ¦¬λŠ” λŒ€μƒ */
	protected Drawable drawable;
	
	/* κ·Έλ¦¬λŠ” μœ„μΉ˜ */
	private Point position;
	
	/* μƒμ„±μž */
	public DrawCommand(Drawable drawable, Point position) {
		this.drawable = drawable;
		this.position = position;
	}
	
	/* μ‹€ν–‰ */
	@Override
	public void execute() {
		drawable.draw(position.x, position.y);
	}
}
  • Command μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬, 점을 κ·Έλ¦¬λŠ” λͺ…령을 ν‘œν˜„ν•œ ν΄λž˜μŠ€μ΄λ‹€.
  • 이 ν΄λž˜μŠ€μ—λŠ” drawable, positionμ΄λΌλŠ” 두 개의 ν•„λ“œκ°€ μžˆλ‹€.
  • drawable ν•„λ“œμ—λŠ” 그리기λ₯Ό μ‹€ν–‰ν•  λŒ€μƒμ„ μ €μž₯ν•œλ‹€.
  • position ν•„λ“œλŠ” 그리기λ₯Ό μ‹€ν–‰ν•  μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • Point ν΄λž˜μŠ€λŠ” java.awt νŒ¨ν‚€μ§€μ— μ •μ˜λ˜μ–΄ μžˆλŠ” 클래슀둜 X μ’Œν‘œμ™€ Y μ’Œν‘œλ₯Ό κ°–λŠ” 2차원 ν‰λ©΄μ˜ μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • μƒμ„±μžμ—μ„œλŠ” 두 ν•„λ“œλ₯Ό 인수둜 λ°›μ•„, ν•΄λ‹Ή μœ„μΉ˜μ— 점을 κ·Έλ¦¬λΌλŠ” λͺ…령을 μƒμ„±ν•œλ‹€.
  • execute() λ©”μ„œλ“œμ—μ„œλŠ” drawable ν•„λ“œμ˜ draw() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€.

Drawable μΈν„°νŽ˜μ΄μŠ€

1
2
3
4
5
package drawer;

public interface Drawable {
	public abstract void draw(int x, int y);
}
  • κ·Έλ¦¬λŠ” λŒ€μƒμ„ λ‚˜νƒ€λ‚Έλ‹€.
  • draw()λŠ” κ·Έλ¦¬λŠ” λ©”μ„œλ“œμ΄λ‹€.

DrawCanvas 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package drawer;

import command.MacroCommand;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;

public class DrawCanvas extends Canvas implements Drawable {
	/* κ·Έλ¦¬λŠ” 색 */
	private Color color = Color.red;
	
	/* κ·Έλ¦¬λŠ” 점의 λ°˜μ§€λ¦„ */
	private int radius = 6;
	
	/* 이λ ₯ */
	private MacroCommand history;
	
	/* μƒμ„±μž */
	public DrawCanvas(int width, int height, MacroCommand history) {
		setSize(width, height);
		setBackground(Color.white);
		this.history = history;
	}
	
	/* 이λ ₯ 전체 λ‹€μ‹œ 그리기 */
	@Override
	public void paint(Graphics g) {
		history.execute();
	}
	
	/* 그리기 */
	@Override
	public void draw(int x, int y) {
		Graphics g = getGraphics();
		g.setColor(color);
		g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
	}
}
  • Drawable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 클래슀둜, java.awt.Canvas 클래슀의 ν•˜μœ„ ν΄λž˜μŠ€μ΄λ‹€.
  • μžμ‹ μ΄ κ·Έλ €μ•Ό ν•  λͺ…λ Ή 집합은 history ν•„λ“œμ— μ €μž₯λœλ‹€.
  • μƒμ„±μžλŠ” λ„ˆλΉ„μ™€ 높이, λ“œλ‘œμž‰ λ‚΄μš©(history)을 λ°›μ•„μ„œ DrawCanvas의 μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•œλ‹€.
  • 이 μ•ˆμ—μ„œ ν˜ΈμΆœν•˜λŠ” setSize()λ‚˜ setBackground() λ©”μ„œλ“œλŠ” 각각 크기와 배경색을 μ§€μ •ν•œλ‹€.
  • paint() λ©”μ„œλ“œλŠ” DrawCanvasλ₯Ό λ‹€μ‹œ 그릴 ν•„μš”κ°€ μžˆμ„ λ•Œ, java 처리 μ‹œμŠ€ν…œμ—μ„œ ν˜ΈμΆœλ˜λŠ” λ©”μ„œλ“œμ΄λ‹€.
  • ν•΄μ•Ό ν•  μ²˜λ¦¬λŠ” history.execute()λ₯Ό ν˜ΈμΆœν•˜λŠ” 것 뿐이닀.
  • μ΄κ²ƒλ§ŒμœΌλ‘œλ„ history에 기둝된 λͺ…λ Ή 집합이 λ‹€μ‹œ μ‹€ν–‰λœλ‹€.
  • draw() λ©”μ„œλ“œλŠ” Drawable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³ μž μ •μ˜λœ λ©”μ„œλ“œμ΄λ‹€.
  • 이 μ•ˆμ—μ„œ g.setColor() λ©”μ„œλ“œλ‘œ 색상을 μ§€μ •ν•˜κ³ , g.fillOval() λ©”μ„œλ“œλ‘œ 원을 μ§€μ •ν•œλ‹€.

Main 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import command.*;
import drawer.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JFrame implements MouseMotionListener, WindowListener {
	/* 그리기 이λ ₯ */
	private MacroCommand history = new MacroCommand();
	
	/* κ·Έλ¦¬λŠ” μ˜μ—­ */
	private DrawCanvas canvas = new DrawCanvas(400, 400, history);
	
	/* μ‚­μ œ λ²„νŠΌ */
	private JButton clearButtonΒ = new JButton("clear");
	
	/* μƒμ„±μž */
	public Main(String title) {
		super(title);
		
		this.addWindowListener(this);
		canvas.addMouseMotionListener(this);
		clearButton.addActionListener(e -> {
			history.clear();
			canvas.repaint();
		});
		
		Box buttonBox = new Box(BoxLayout.X_AXIS);
		buttonBox.add(clearButton);
		Box mainBox = new Box(BoxLayout.Y_AXIS);
		mainBox.add(buttonBox);
		mainBox.add(canvas);
		getContentPane().add(mainBox);
		
		pack();
		setVisible(true);
	}
	
	/* MouseMotionListener용 */
	@Override
	public void mouseMoved(MouseEvent e) { }
	
	@Override
	public void mouseDragged(MouseEvent e) {
		Command cmd = new DrawCommand(canvas, e.getPoint());
		history.append(cmd);
		cmd.execute();
	}
	
	/* WindowListener용 */
	@Override
	public void windowClosing(WindowEvent e) {
		System.exit(0);
	}
	
	@Override public void windowActivated(WindowEvent e) {}
	@Override public void windowClosed(WindowEvent e) {}
	@Override public void windowDeactivated(WindowEvent e) {}
	@Override public void windowDeiconified(WindowEvent e) {}
	@Override public void windowIconified(WindowEvent e) {}
	@Override public void windowOpened(WindowEvent e) {}
	
	public static void main(String[] args) {
		new Main("Command Pattern Sample");
	}
}
  • 예제 ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜κΈ° μœ„ν•œ ν΄λž˜μŠ€λ‹€.
  • history ν•„λ“œλŠ” 그리기 이λ ₯을 μ €μž₯ν•œλ‹€.
  • μ΄λŠ” λ‚˜μ€‘μ— DrawCanvas μΈμŠ€ν„΄μŠ€μ— μ „λ‹¬ν•˜λŠ” 것과 λ™μΌν•˜λ‹€.
  • 즉 그리기 이λ ₯은 Main의 μΈμŠ€ν„΄μŠ€μ™€ DrawCanvasμ—μ„œ κ³΅μœ λœλ‹€κ³  λ³Ό 수 μžˆλ‹€.
  • canvas ν•„λ“œλŠ” κ·Έλ¦¬λŠ” μ˜μ—­μ΄λ‹€.
  • clearButton ν•„λ“œλŠ” κ·Έλ¦° 점을 μ§€μš°λŠ” μ‚­μ œ λ²„νŠΌμ΄κ³ , JButton ν΄λž˜μŠ€λŠ” javax.swing νŒ¨ν‚€μ§€ 클래슀둜 λ²„νŠΌμ„ ν‘œν˜„ν•œ 것이닀.
  • μƒμ„±μžμ—μ„œλŠ” 마우슀 클릭 λ“±μ˜ 이벀트λ₯Ό λ°›λŠ” λ¦¬μŠ€λ„ˆλ₯Ό μ„€μ •ν•˜κ³  μ»΄ν¬λ„ŒνŠΈλ₯Ό λ°°μΉ˜ν•˜κ³  μžˆλ‹€.
  • μ»΄ν¬λ„ŒνŠΈ λ ˆμ΄μ•„μ›ƒμ€ λ‹€μŒκ³Ό κ°™λ‹€.

  • clearButton.addActionListener() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” κ³³μ—μ„œ λžŒλ‹€μ‹μ„ μ΄μš©ν•΄ 그리기 이λ ₯을 μ§€μš΄ 후에 λ‹€μ‹œ 그리기 처리λ₯Ό μ„€μ •ν–ˆλ‹€.
  • mouseMoved(), mouseDragged() λ©”μ„œλ“œλŠ” MouseMotionListener μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 것이닀.
  • μ—¬κΈ°μ„œ 마우슀λ₯Ό λ“œλž˜κ·Έν•  λ•Œ (mouseDragged)에 이 μœ„μΉ˜μ— 점을 κ·Έλ¦¬λΌλŠ” λͺ…령을 λ§Œλ“€μ—ˆλ‹€.
  • λ§Œλ“  λͺ…령은 history.append(cmd)둜 μ‹€ν–‰ 이λ ₯에 μΆ”κ°€ν•œ ν›„ cmd.execute()둜 μ¦‰μ‹œ μ‹€ν–‰ν•˜κ³  μžˆλ‹€.
  • window...둜 μ‹œμž‘ν•˜λŠ” λ©”μ„œλ“œ 그룹은 WindowListener μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ 것이닀.
  • μ—¬κΈ°μ—μ„œλŠ” μ’…λ£Œ 처리만 κ΅¬ν˜„ν–ˆλ‹€.
  • main() λ©”μ„œλ“œμ—μ„œλŠ” Main 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ μ‹€ν–‰ν•˜κ³  μžˆλ‹€.

Command νŒ¨ν„΄μ˜ λ“±μž₯인물

Command μΈν„°νŽ˜μ΄μŠ€

  • λͺ…λ Ήμ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ” λͺ…λ Ή(Command) 역을 λ§‘μ•˜λ‹€.

MacroCommand, DrawCommand 클래슀

  • Command μ—­μ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” ꡬ체적인 λͺ…λ Ή(ConcreteCommand) 역을 λ§‘μ•˜λ‹€.

DrawCanvas 클래슀

  • Commandκ°€ λͺ…령을 μ‹€ν–‰ν•  λ•Œ λŒ€μƒμ΄ λœλ‹€.
  • λͺ…λ Ήμ˜ μˆ˜μ‹ μžλ‘œ λΆ€λ₯΄λŠ” μˆ˜μ‹ μž(Receiver) 역을 λ§‘μ•˜λ‹€.

Main 클래슀

  • ConcreateCommandλ₯Ό μƒμ„±ν•˜κ³  κ·Έ λ•Œ Receiverλ₯Ό ν• λ‹Ήν•˜λŠ” 의뒰자(Client) 역을 λ§‘μ•˜λ‹€.
  • Main ν΄λž˜μŠ€λŠ” 마우슀의 λ“œλž˜κ·Έμ— λ§žμΆ”μ–΄ DrawCommand μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œλ‹€.

Main, DrawCanvas 클래슀

  • Command μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν˜ΈμΆœν•˜μ—¬ λͺ…λ Ή 싀행을 μ‹œμž‘ν•˜λŠ” 호좜자(Invoker) 역을 λ§‘μ•˜λ‹€.
  • 이 두 ν΄λž˜μŠ€λŠ” Command μΈν„°νŽ˜μ΄μŠ€μ˜ execute() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€.

μ±…μ—μ„œ μ œμ‹œν•˜λŠ” 힌트

λͺ…령이 κ°€μ Έμ•Ό ν•˜λŠ” μ •λ³΄λŠ”?

  • λͺ…령이 μ–΄λŠ μ •λ„μ˜ 정보λ₯Ό κ°€μ§ˆ μ§€λŠ” λͺ©μ μ— 따라 달라진닀.
  • DrawCommand ν΄λž˜μŠ€μ—λŠ” κ·Έλ¦¬λŠ” 점의 μœ„μΉ˜ μ •λ³΄λ§Œ κ°–κ³  μžˆμ„ 뿐, 점의 ν¬κΈ°λ‚˜ 색상, λͺ¨μ–‘ λ“±μ˜ μ •λ³΄λŠ” μ—†λ‹€.
  • λ˜ν•œ 이벀트 λ°œμƒ μ‹œκ° 정보λ₯Ό κ°–κ³  μžˆλ‹€λ©΄ λ‹¨μˆœν•œ 그리기가 μ•„λ‹ˆλΌ 마우슀 λ™μž‘μ˜ μ™„κΈ‰κΉŒμ§€ μž¬ν˜„ν•  수 μžˆλ‹€.
  • DrawCommand ν΄λž˜μŠ€μ—λŠ” κ·Έλ¦¬λŠ” λŒ€μƒμ„ λ‚˜νƒ€λ‚΄λŠ” drawable ν•„λ“œλ„ μžˆλ‹€.
  • 예제 ν”„λ‘œκ·Έλž¨μ—μ„œ DrawCanvas μΈμŠ€ν„΄μŠ€λŠ” ν•˜λ‚˜ 뿐이고, λͺ¨λ“  κ·Έλ¦¬κΈ°λŠ” κ·Έκ³³μ—μ„œ 이루어지기 λ•Œλ¬Έμ—, 이 drawable ν•„λ“œκ°€ 크게 μ˜λ―Έκ°€ μ—†λ‹€.
  • κ·ΈλŸ¬λ‚˜ κ·Έλ¦¬λŠ” λŒ€μƒμ΄ μ—¬λŸ¬ 개 μ‘΄μž¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μΌ 경우 이런 ν•„λ“œκ°€ 도움이 λœλ‹€.
  • ConcreateCommand μ—­ μžμ‹ μ΄ Receiver 역을 μ•Œκ³  μžˆμ–΄μ„œ ConcreateCommand 역을 λˆ„κ°€ κ΄€λ¦¬ν•˜κ³  κ°€μ§€κ³  μžˆλ“  μ–Έμ œλ“ μ§€ execute() ν•  수 있기 λ•Œλ¬Έμ΄λ‹€.

이λ ₯의 μ €μž₯

  • 예제 ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” 그리기 이λ ₯을 MacroCommand μΈμŠ€ν„΄μŠ€μ˜ history에 μ €μž₯ν•˜κ³  μžˆλ‹€.
  • 이 μΈμŠ€ν„΄μŠ€λŠ” μ§€κΈˆκΉŒμ§€ κ·Έλ¦° 정보λ₯Ό λͺ¨λ‘ κ°€μ§€κ³  있으며, 파일둜 잘 μ €μž₯해두면 그리기 이λ ₯이 λ³΄μ‘΄λœλ‹€.

μ–΄λŒ‘ν„°

  • 예제 ν”„λ‘œκ·Έλž¨μ˜ Main ν΄λž˜μŠ€μ—λŠ” 두 개의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν–ˆλŠ”λ°, μΈν„°νŽ˜μ΄μŠ€μ˜ λ©”μ„œλ“œ 쀑에 μ‹€μ œλ‘œ μ‚¬μš©ν•˜λŠ” 것은 κ·Έ 일뢀이닀.
  • κ°€λ Ή MouseMotionListener λ©”μ„œλ“œ μ€‘μ—μ„œ μ‚¬μš©ν•˜λŠ” 것은 mouseDragged() λ©”μ„œλ“œ 뿐이닀.
  • 또 ν•˜λ‚˜ 예λ₯Ό λ“€λ©΄, WindowListenerμ—μ„œλŠ” 7개의 λ©”μ„œλ“œ 쀑 windowClosing() λ©”μ„œλ“œλ§Œ μ‚¬μš©ν•œλ‹€.
  • ν”„λ‘œκ·Έλž˜λ°μ„ κ°„κ²°ν•˜κ²Œ ν•˜κΈ° μœ„ν•΄ μ–΄λŒ‘ν„° ν΄λž˜μŠ€λ“€μ΄ java.awt.event νŒ¨ν‚€μ§€μ— μ€€λΉ„λ˜μ–΄ μžˆλ‹€.
  • MouseMotionListener μΈν„°νŽ˜μ΄μŠ€μ—λŠ” MouseMotionAdapter 클래슀, WindowListener μΈν„°νŽ˜μ΄μŠ€μ—λŠ” WindowAdapter ν΄λž˜μŠ€κ°€ μ€€λΉ„λ˜μ–΄ μžˆλ‹€.
  • μ΄λŸ¬ν•œ μ–΄λŒ‘ν„°λŠ” Adapter νŒ¨ν„΄μ˜ ν•œ μ˜ˆμ΄λ‹€.
  • MouseMotionAdapter μΈν„°νŽ˜μ΄μŠ€λ‘œ 예λ₯Ό λ“€μ–΄ 보면, 이 ν΄λž˜μŠ€λŠ” MouseMotionListener μΈν„°νŽ˜μ΄μŠ€κ°€ μš”κ΅¬ν•˜λŠ” λ©”μ„œλ“œλ₯Ό λͺ¨λ‘ κ΅¬ν˜„ν•˜μ§€λ§Œ, κ·Έ λ‚΄μš©μ€ λͺ¨λ‘ λΉ„μ–΄μžˆλ‹€.
  • λ”°λΌμ„œ MouseMotionAdapter의 ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€κ³  ν•„μš”ν•œ λ©”μ„œλ“œλ§Œ κ΅¬ν˜„ν•˜λ©΄ λͺ©μ μ„ 달성할 수 μžˆλ‹€.
  • 특히 Java의 읡λͺ… 클래슀λ₯Ό μ‘°ν•©ν•΄μ„œ μ–΄λŒ‘ν„°λ₯Ό μ‚¬μš©ν•˜λ©΄ ν•œμΈ΅ 더 ν”„λ‘œκ·Έλž¨μ„ μŠ€λ§ˆνŠΈν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€.
MouseMotionListenerλ₯Ό μ‚¬μš©ν•˜λŠ” 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main extends JFrame implements MouseMotionListener, WindowListener {
	// ...
	
	public Main(String title) {
		// ... 
		
		canvas.addMouseMotionListener(this);
		
		// ...
	}
	
	public void mouseMoved(MouseEvent e) { }
	public void mouseDragged(MouseEvent e) {
		Command cmd = new DrawCommand(canvas, e.getPoint());
		history.append(cmd);
		cmd.execute();
	}
	
	// ...
}
MouseMotionAdapterλ₯Ό μ‚¬μš©ν•˜λŠ” 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main extends JFrame implements WindowListener {
	// ...
	
	public Main(String title) {
		// ... 
		
		canvas.addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseDragged(MouseEvent e) {
				Command cmd = new DrawCommand(canvas, e.getPoint());
				history.append(cmd);
				cmd.execute();
			}
		});
		
		// ...
	}
	
	// ...
}
  • 읡λͺ… 클래슀 ꡬ문은 μ΅μˆ™ν•˜μ§€ μ•ŠμœΌλ©΄ 읽기 μ–΄λ ΅μ§€λ§Œ, 주의 깊게 μ‚΄νŽ΄λ³΄λ©΄ λ‹€μŒκ³Ό 같은 사싀을 μ•Œ 수 μžˆλ‹€.
  1. new MouseMotionAdapter()λŠ” 마치 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 식과 λΉ„μŠ·ν•˜λ‹€.
  2. 뒀에 μ΄μ–΄μ§€λŠ” {...}λŠ” λ©”μ„œλ“œ μ •μ˜μ™€ λΉ„μŠ·ν•˜λ‹€.
  • MouseMotionAdapter 클래슀의 ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€μ–΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œλ‹€.
  • μ˜€λ²„λΌμ΄λ“œν•  λ©”μ„œλ“œλ§Œ κ΅¬ν˜„ν•˜λ©΄, λ‚˜λ¨Έμ§€λŠ” 아무것도 μ“Έ ν•„μš”κ°€ μ—†μœΌλ―€λ‘œ μš©μ΄ν•˜λ‹€.
This post is licensed under CC BY 4.0 by the author.