Post

⛓️ Java Design-Pattern β…‘ - Iterator

⛓️ Java Design-Pattern β…‘ - Iterator

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 반볡문
for (int i = 0; i < arr.length; i++) {
	System.out.println(arr[i]);
}

// μš”μ†Œ
arr[0]
arr[1]
arr[2]

// ...

arr[i]

// ...

arr[arr.length - 1]
  • Iterator νŒ¨ν„΄μ€ λ°˜λ³΅λ¬Έμ—μ„œ μ‚¬μš©λ˜λŠ” λ³€μˆ˜ i의 κΈ°λŠ₯을 μΆ”μƒν™”ν•˜μ—¬ μΌλ°˜ν™”ν•œ νŒ¨ν„΄μ΄λ‹€.
  • ν•΄λ‹Ή νŒ¨ν„΄μ€ μš”μ†Œκ°€ λͺ¨μ—¬ μžˆμ„ λ•Œ 이λ₯Ό μˆœμ„œλŒ€λ‘œ 가리킀며 전체λ₯Ό κ²€μƒ‰ν•˜κ³  동일 처리λ₯Ό λ°˜λ³΅ν•œλ‹€.

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

  • μœ„ λ‹€μ΄μ–΄κ·Έλž¨μ€ 업무에 ν•΄λ‹Ήν•˜λŠ” ν•˜μœ„ 업무λͺ…을 μ°¨λ‘€λŒ€λ‘œ ν‘œμ‹œν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ λ‚˜νƒ€λ‚Έλ‹€.
  • 업무와 ν•˜μœ„ μ—…λ¬΄λŠ” ν•„μžκ°€ μ§„ν–‰ν•˜λŠ” 토이 ν”„λ‘œμ νŠΈ 도메인이닀.
  • ν”„λ‘œμ νŠΈλŠ” μ—…λ¬΄λ‘œ κ΅¬μ„±λ˜μ–΄ 있고, 각 μ—…λ¬΄λŠ” ν•˜μœ„ μ—…λ¬΄λ‘œ ꡬ성할 μ˜ˆμ •μ΄λ‹€.
1
2
3
public interface Iterable<E> {
	public abstract Iterator<E> iterator();
}
  • 반볡 κ°€λŠ₯ν•œ 객체닀.
  • iterator() λ©”μ„œλ“œλ₯Ό 톡해 μ‹€μ œλ‘œ λ°˜λ³΅μ„ μˆ˜ν–‰ν•˜λŠ” Iterator<E> 반볡자λ₯Ό λ°˜ν™˜ν•œλ‹€.
1
2
3
4
public interface Iterator<E> {
	public abstract boolean hasNext();
	public abstract E next();
}
  • λ°˜λ³΅μ„ μˆ˜ν–‰ν•˜λŠ” 객체닀.
  • hasNext() λ©”μ„œλ“œλ₯Ό 톡해 λ‹€μŒ μš”μ†Œμ˜ 쑴재 μ—¬λΆ€λ₯Ό λ°˜ν™˜ν•œλ‹€.
  • next() λ©”μ„œλ“œλ₯Ό 톡해 μš”μ†Œλ₯Ό ν•˜λ‚˜ λ°˜ν™˜ν•˜κ³ , μΈλ±μŠ€κ°€ λ‹€μŒ μš”μ†Œλ₯Ό 가리킀도둝 ν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SubTask {
	private String name;
	private String description
	
	public SubTask(String name, String description) {
		 this.name = name;
		 this.description = description;
	}
	
	public String getName() {
		return name;
	}
	
	public String getDescription() { 
		return description;
	}
}
  • ν•˜μœ„μ—…λ¬΄μ— ν•΄λ‹Ήν•˜λŠ” ν΄λž˜μŠ€λ‹€.
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
import java.util.Iterator;

public class Task implements Iterable<SubTask> {
	private SubTask[] subTasks;
	private int last = 0;
	
	public Task(int maxsize) {
		this.subTasks = new SubTasks[maxsize];
	}
	
	public Book getSubTaskAt(int index) {
		return subTasks[index];
	}
	
	public void appendSubTask(SubTask subTask) {
		 this.subTasks[last] = subTask;
		 last++;
	}
	
	public int getLength() {
		return last;
	}
	
	@Override
	public Iterator<SubTask> iterator {
		return new TaskIterator(this);
	} 
}
  • 업무에 ν•΄λ‹Ήν•˜λŠ” ν΄λž˜μŠ€λ‹€.
  • μƒμ„±μžμ˜ 인수λ₯Ό 톡해 ν•΄λ‹Ή μ—…λ¬΄μ˜ μ΅œλŒ€ ν•˜μœ„ 업무 κ°œμˆ˜κ°€ μ •ν•΄μ§„λ‹€.
  • ν•„λ“œ μ ‘κ·Όμ œν•œμžλ₯Ό private둜 μ„ μ–Έν•˜μ—¬ μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 λ°©μ§€ν•œλ‹€.
  • getSubTaskAt(int index) λ©”μ„œλ“œλ₯Ό 톡해 ν˜„μž¬ μΈλ±μŠ€κ°€ μ–΄λ–€ ν•˜μœ„ 업무λ₯Ό κ°€λ¦¬ν‚€λŠ” μ§€ μ•Œ 수 μžˆλ‹€.
  • appendSubTask(SubTask subTask) λ©”μ„œλ“œλ₯Ό 톡해 ν•˜μœ„ 업무λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.
  • getLength() λ©”μ„œλ“œλ₯Ό 톡해 ν˜„μž¬ ν•˜μœ„ μ—…λ¬΄μ˜ 개수λ₯Ό μ•Œ 수 μžˆλ‹€.
  • iterator() λ©”μ„œλ“œλ₯Ό 톡해 ν•˜μœ„ 업무λ₯Ό μ°¨λ‘€λŒ€λ‘œ μˆœνšŒν•˜λ©° μ²˜λ¦¬ν•  수 μžˆλŠ” TaskIterator() 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œλ‹€.
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
import java.util.Iterator;
import java.util.NoSuchElementException;

public class TaskIterator implements Iterator<Book> {
	private Task task;
	private int index;
	
	public TaskIterator(Task task) {
		this.task = task;
		this.index = 0;
	}
	
	@Override
	public boolean hasNext() {
		if (index < task.getLength()) {
			return true;
		} else {
			return false;
		}
	}
	
	@Override
	public SubTask next() {
		if (!hasNext) {
			throw new NoSuchElementException();
		}
		SubTask subTask = task.getSubTaskAt(index);
		index++;
		return subTask;
	}
}
  • 업무 λ°˜λ³΅μžμ— ν•΄λ‹Ήν•˜λŠ” ν΄λž˜μŠ€λ‹€.
  • Task ν•„λ“œλŠ” ν˜„μž¬ λŒ€μƒμœΌλ‘œ ν•˜λŠ” 업무이며, index ν•„λ“œλŠ” 가리킀고 μžˆλŠ” ν•˜μœ„ μ—…λ¬΄μ˜ μˆœμ„œλ₯Ό μ˜λ―Έν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Main {
	public static void main(String[] args) {
		Task task = new Task(3);
		task.appendSubTask(new SubTask("섀계", "ν”„λ‘œμ νŠΈ 섀계λ₯Ό μ˜λ―Έν•œλ‹€."));
		task.appendSubTask(new SubTask("κ΅¬ν˜„", "μ„€κ³„λŒ€λ‘œ κ΅¬ν˜„ν•œλ‹€."));
		task.appendSubTask(new SubTask("ν…ŒμŠ€νŠΈ", "κ΅¬ν˜„ν•œ 뢀뢄을 ν…ŒμŠ€νŠΈν•œλ‹€."));
		
		// λͺ…μ‹œμ  μ‚¬μš©
		Iterator<SubTask> it = task.iterator();
		while (it.hasNext) {
			SubTask subTask = it.next();
			System.out.println(subTask.getName());
			System.out.println(subTask.getDescription());
		}
		
		// ν™•μž₯ forλ¬Έ μ‚¬μš©
		/*
		for (SubTask subTask : Task) {
			System.out.println(subTask.getName());
			System.out.println(subTask.getDescription());
		}
		*/
	}
}
  • ν”„λ‘œκ·Έλž¨μ˜ 메인 ν΄λž˜μŠ€μ΄λ‹€.
  • λͺ…μ‹œμ  μ‚¬μš© μ½”λ“œμ™€ for-each문을 μ‚¬μš©ν•œ μ½”λ“œλŠ” μ™„μ „νžˆ 같은 λ™μž‘μ„ μˆ˜ν–‰ν•œλ‹€.
  • 일반적으둜 μžλ°”μ˜ for-each문은 Iterator μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€μ˜ 경우, λ‚΄λΆ€μ μœΌλ‘œ Iteratorλ₯Ό μ‚¬μš©ν•˜μ—¬ μ²˜λ¦¬ν•œλ‹€.

체크 포인트

βœ… μ–΄λ–»κ²Œ κ΅¬ν˜„ν•˜λ“ Β Iteratorλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

1
2
3
4
5
6
Iterator<SubTask> it = task.iterator();
while (it.hasNext) {
	SubTask subTask = it.next();
	System.out.println(subTask.getName());
	System.out.println(subTask.getDescription());
}
  • Iterator νŒ¨ν„΄μ„ μ‚¬μš©ν•¨μœΌλ‘œμ¨ κ΅¬ν˜„κ³Ό λΆ„λ¦¬ν•˜μ—¬ λ°˜λ³΅ν•  수 μžˆλ‹€.
  • 상기 μ½”λ“œμ—μ„œΒ while문은 업무 클래슀 κ΅¬ν˜„μ— μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • 업무 μΈμŠ€ν„΄μŠ€μ˜ subTasks ν•„λ“œλ₯Ό λ°°μ—΄μ—μ„œΒ java.util.ArrayList둜 λ³€κ²½ν•œλ‹€κ³  ν•˜μž.
  • 업무 클래슀λ₯Ό μ–΄λ–»κ²Œ λ³€κ²½ν•˜λ“  iterator()Β λ©”μ„œλ“œλ₯Ό κ°–κ³  있고,Β hasNext()와 next()κ°€ λ°”λ₯΄κ²Œ κ΅¬ν˜„λœ μ˜¬λ°”λ₯ΈΒ Iterator<SubTask>을 λ°˜ν™˜ν•˜λ©΄Β while문은 λ³€κ²½ν•˜μ§€ μ•Šμ•„λ„ λ™μž‘ν•œλ‹€.
  • μ΄λŸ¬ν•œ μ˜μ‘΄μ„± λΆ„λ¦¬λŠ” μ½”λ“œ μž¬μ‚¬μš©μ„ μ΄‰μ§„ν•œλ‹€.

βœ… 좔상 ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μž.

  • ꡬ체적인 클래슀만 μ‚¬μš©ν•˜λ©΄ 클래슀 μ‚¬μ΄μ˜ 결합이 κ°•ν•΄μ Έ λΆ€ν’ˆμœΌλ‘œ μž¬μ‚¬μš©ν•˜κΈ° μ–΄λ ΅λ‹€.
  • 결합을 μ•½ν™”ν•˜κ³  μž¬μ‚¬μš©ν•˜κΈ° μ‰½κ²Œ ν•˜κ³ μž 좔상 ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ„μž…ν•΄μ•Ό ν•œλ‹€.

βœ… 반볡자의 집합체 의쑴

  • TaskIterator ν΄λž˜μŠ€λŠ” 업무 ν΄λž˜μŠ€κ°€ μ–΄λ–»κ²Œ κ΅¬ν˜„λ˜μ–΄ μžˆλŠ”μ§€ μ•Œκ³  μžˆμ—ˆκΈ° λ•Œλ¬Έμ—Β getSubTaskAt(int index) λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ‹€μŒ ν•˜μœ„ 업무λ₯Ό κ°€μ Έμ˜¬ 수 μžˆμ—ˆλ‹€.
  • μ΄λŠ” μ—…λ¬΄Β ν΄λž˜μŠ€μ˜ κ΅¬ν˜„μ„ λ°”κΎΌλ‹€λ©΄ TaskIterator 클래슀λ₯Ό μˆ˜μ •ν•΄μ•Ό λœλ‹€λŠ” 말이 λœλ‹€.
  • Iterable<E> ν΄λž˜μŠ€μ™€ Iterator<E> ν΄λž˜μŠ€κ°€ 짝을 이루듯 Task ν΄λž˜μŠ€μ™€ TaskIterator ν΄λž˜μŠ€λ„ 짝을 이룬닀.
  • 사싀 예제 μ½”λ“œμ˜ λ©”μ„œλ“œ λͺ…은 ν˜Όλ™ν•˜κΈ° 쉽닀.
    • next()Β λ©”μ„œλ“œλŠ” ν˜„μž¬ μ²˜λ¦¬ν•˜λŠ” μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜λŠ”μ§€, λ‹€μŒ μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜λŠ”μ§€ λͺ¨ν˜Έν•˜λ‹€.
    • μ •ν™•νžˆ ν‘œν˜„ν•˜λ©΄ CurrentElementAndAdvanceToNextPosition() λ©”μ„œλ“œκ°€ λ§žλ‹€.

βœ… 볡수의 반볡자

  • ν˜„μž¬ μ–΄λ””κΉŒμ§€ μ‘°μ‚¬ν–ˆλŠ”μ§€ κΈ°μ–΅ν•˜λŠ” ꡬ쑰λ₯Ό 집합체 μ—­ν•  외뢀에 λ‘λŠ” 것이 IteratorΒ νŒ¨ν„΄μ˜ νŠΉμ§• 쀑 ν•˜λ‚˜λ‹€.
  • 이런 νŠΉμ§•μ— 따라 ν•˜λ‚˜μ˜ ꡬ체적인 집합체 역할에 λŒ€ν•΄ μ—¬λŸ¬ 개의 ꡬ체적인 반볡자 역할을 λ§Œλ“€ 수 μžˆλ‹€.

βœ… deleteIterator() λ©”μ„œλ“œλŠ” ν•„μš” μ—†λ‹€.

  • Javaμ—μ„œ μ‚¬μš©λ˜μ§€ μ•ŠλŠ” μΈμŠ€ν„΄μŠ€λŠ” Garbage-collection에 μ˜ν•΄ μžλ™μœΌλ‘œ μ‚­μ œλœλ‹€.

회고

  • Java의 for-eachλ¬Έ λ°°ν›„μ—μ„œλŠ” μš°λ¦¬κ°€ μž‘μ„±ν•œ Iterator νŒ¨ν„΄μ΄ μ‚¬μš©λœλ‹€λŠ” 점을 κΈ°μ–΅ν•΄μ•Όκ² λ‹€.
This post is licensed under CC BY 4.0 by the author.