서론
제가 블로그 포스팅을 1일 1포스팅을 해보려고 했는데 개인 사정으로 너무 바빠서 결국 실패해버렸네요..ㅎ
그런 이유로 오랜만에 포스팅을 해보려고 합니다!
이번시간에는 디자인패턴에 이터레이터 패턴에 대해서 포스팅을 해보려고 합니다!
이터레이터 패턴은 디자인 패턴 중 하나로, 여러분이 컬렉션을 다루는 데 있어 매우 유용한 도구입니다. 이터레이터 패턴이 무엇인지, 왜 필요한지, 그리고 어떻게 사용하는지에 대해 자세히 알아보도록 하겠습니다.
이터레이터 패턴이란?
이터레이터 패턴은 객체의 컬렉션, 즉 목록을 순회하는 방법을 제공하는 디자인 패턴입니다. 쉽게 말해서, 컬렉션 안의 각 요소에 순차적으로 접근할 수 있는 방법을 제공하는 것이죠. 그런데 왜 이런 패턴이 필요한 걸까요?
왜 이터레이터 패턴이 필요한가?
컬렉션은 여러 가지 형태로 존재합니다. 배열, 리스트, 스택, 큐, 트리 등 다양한 데이터 구조가 있죠. 이런 복잡한 데이터 구조를 사용하다 보면, 각 요소에 접근하는 방법이나 순서 등이 복잡해질 수 있습니다. 이럴 때 이터레이터 패턴을 사용하면, 컬렉션의 내부 구조에 대해 알 필요 없이 간단하게 요소에 접근할 수 있습니다.
이터레이터 패턴은 이처럼 컬렉션의 구조를 감추고, 통일된 인터페이스를 제공합니다. 이로 인해 클라이언트 코드는 컬렉션의 구현에 의존하지 않게 되며, 이는 코드의 유연성과 재사용성을 높여줍니다.
그럼 이제 이터레이터 패턴을 어떻게 사용하는지, Swift와 Java 언어를 통해 알아보도록 하겠습니다.
Swift 예제
protocol Iterator {
associatedtype Element
func next() -> Element?
}
struct MyCollection {
let items: [Int]
}
extension MyCollection: Sequence {
func makeIterator() -> Iterator {
return MyIterator(self)
}
struct MyIterator: Iterator {
let collection: MyCollection
var index = 0
init(_ collection: MyCollection) {
self.collection = collection
}
mutating func next() -> Int? {
guard index < collection.items.count else { return nil }
let item = collection.items[index]
index += 1
return item
}
}
}
let myCollection = MyCollection(items: [1, 2, 3, 4, 5])
for item in myCollection {
print(item)
}
Swift에서는 이터레이터 패턴을 구현하기 위해 Iterator 프로토콜을 사용합니다. Iterator 프로토콜은 next() 메서드를 제공하며, 이 메서드는 컬렉션의 다음 요소를 반환하거나, 더 이상 요소가 없을 경우 nil을 반환합니다. 이 프로토콜을 따르는 MyIterator 구조체를 정의하였습니다. 이 구조체는 컬렉션과 인덱스를 저장하며, next() 메서드를 통해 컬렉션의 요소에 접근합니다.
또한, MyCollection 타입은 Sequence 프로토콜을 따르도록 확장하였습니다. Sequence 프로토콜은 makeIterator() 메서드를 통해 이터레이터를 반환합니다. 이를 통해 for-in 루프를 사용하여 컬렉션의 요소를 순회할 수 있습니다.
Java 예제
import java.util.Iterator;
import java.util.Arrays;
import java.util.List;
public class MyCollection implements Iterable<Integer> {
private List<Integer> items;
public MyCollection(Integer... items) {
this.items = Arrays.asList(items);
}
@Override
public Iterator<Integer> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<Integer> {
private int index = 0;
@Override
public boolean hasNext() {
return index < items.size();
}
@Override
public Integer next() {
return items.get(index++);
}
}
public static void main(String[] args) {
MyCollection myCollection = new MyCollection(1, 2, 3, 4, 5);
for (Integer item : myCollection) {
System.out.println(item);
}
}
}
Java에서는 Iterable 인터페이스를 사용하여 이터레이터 패턴을 구현합니다. Iterable 인터페이스는 iterator() 메서드를 제공하며, 이 메서드는 Iterator 인터페이스를 구현하는 객체를 반환합니다.
Iterator 인터페이스는 hasNext()와 next() 두 가지 메서드를 제공합니다. hasNext()는 컬렉션에 다음 요소가 있는지 확인하고, next()는 다음 요소를 반환합니다. MyCollection 클래스는 Iterable 인터페이스를 구현하며, MyIterator 내부 클래스는 Iterator 인터페이스를 구현합니다.
마무리
이렇게 이터레이터 패턴을 사용하면, 컬렉션의 내부 구조를 숨기고 통일된 인터페이스를 제공하여 클라이언트 코드가 컬렉션의 구현에 의존하지 않도록 할 수 있습니다. 이는 코드의 유연성과 재사용성을 높여주며, 개발자가 컬렉션의 요소를 순회하는 방법에 대해 신경 쓸 필요를 없애줍니다.
이터레이터 패턴은 디자인 패턴 중 하나이지만, 그 중요성과 유용성 때문에 많은 프로그래밍 언어에서 기본적으로 제공하는 기능 중 하나입니다. 이터레이터 패턴을 잘 이해하고 사용한다면, 여러분의 코드는 훨씬 더 깔끔하고 유지보수하기 쉬워질 것입니다.
감사합니다.
틀린 부분이 있거나 더 좋은 내용 훈수 환영합니다!
공감과 댓글 부탁드립니다.
'CS > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] MVC 패턴 이해하고 활용하기 (0) | 2024.01.15 |
---|---|
[디자인패턴] 프록시 패턴(Proxy Pattern) (2) | 2023.10.22 |
[디자인패턴] 옵저버 패턴(Observer Pattern) (2) | 2023.10.21 |
[디자인 패턴] 팩토리 패턴과 전략 패턴의 개념과 예제 소스 (2) | 2023.10.02 |
[디자인 패턴] 디자인 패턴과 싱글톤 패턴 (2) | 2023.05.24 |