디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제를 해결하기 위한 일반적인 솔루션입니다. 루비(Ruby) 같은 객체 지향 프로그래밍 언어에서는 이러한 패턴을 활용하여 코드의 재사용성과 가독성을 높일 수 있습니다. 이번 글에서는 이터레이터(Iterator) 패턴에 대해 알아보고, 이를 루비에서 어떻게 구현할 수 있는지 살펴보겠습니다.
이터레이터 패턴은 컬렉션 객체의 내부 구조를 노출하지 않고도 그 컬렉션의 요소를 순차적으로 접근할 수 있게 해주는 디자인 패턴입니다. 이 패턴은 컬렉션의 요소를 반복(iterate)하는 방법을 제공하며, 다양한 데이터 구조에서 요소를 일관되게 탐색할 수 있도록 도와줍니다.
이제 루비에서 이터레이터 패턴을 어떻게 구현할 수 있는지 살펴보겠습니다. 먼저, 간단한 이터레이터 클래스를 정의해 보겠습니다.
이터레이터 클래스를 정의하기 위해서는 먼저 컬렉션을 저장할 클래스와 이터레이터 클래스를 만들어야 합니다.
class MyCollection def initialize @items = [] end def add(item) @items << item end def each @items.each { |item| yield(item) } end end
위의 코드에서 MyCollection
클래스는 아이템을 저장하는 배열인 @items
를 가지고 있습니다. add
메서드는 아이템을 추가하는 역할을 하며, each
메서드는 블록을 사용하여 각 아이템을 순회합니다.
이제 MyCollection
클래스를 사용하여 이터레이터를 테스트해 보겠습니다.
collection = MyCollection.new collection.add("사과") collection.add("바나나") collection.add("체리") collection.each do |item| puts item end
위의 코드는 MyCollection
클래스의 인스턴스를 생성하고, 과일 이름을 추가한 후, each
메서드를 사용하여 모든 과일 이름을 출력합니다. 이처럼 이터레이터를 사용하면 컬렉션의 요소를 간편하게 순회할 수 있습니다.
기본적인 이터레이터를 구현한 후, 이제는 좀 더 발전된 이터레이터를 만들어 보겠습니다. 예를 들어, 이터레이터에 상태를 추가하여 다음 요소로 이동하거나 이전 요소로 돌아갈 수 있도록 구현할 수 있습니다.
class AdvancedIterator def initialize(collection) @collection = collection @current_index = 0 end def next return nil if @current_index >= @collection.size item = @collection[@current_index] @current_index += 1 item end def has_next? @current_index < @collection.size end def reset @current_index = 0 end end
위의 AdvancedIterator
클래스는 컬렉션을 순회할 수 있는 상태를 가지며, next
, has_next?
, reset
메서드를 통해 요소를 순회하고, 다음 요소가 있는지 확인하며, 이터레이터를 초기 상태로 되돌릴 수 있습니다.
이제 AdvancedIterator
클래스를 사용하여 이터레이터를 테스트해 보겠습니다.
collection = MyCollection.new collection.add("사과") collection.add("바나나") collection.add("체리") iterator = AdvancedIterator.new(collection) while iterator.has_next? puts iterator.next end iterator.reset puts "이터레이터를 초기화한 후:" while iterator.has_next? puts iterator.next end
위의 코드는 AdvancedIterator
를 사용하여 컬렉션의 요소를 순회합니다. has_next?
메서드를 사용하여 다음 요소가 있는지 확인하고, next
메서드를 사용하여 요소를 가져옵니다. 이터레이터를 초기화한 후 다시 순회하는 것도 가능합니다.
루비는 이미 다양한 내장 이터레이터를 제공합니다. 배열, 해시, 문자열 등 여러 컬렉션 객체에서 사용할 수 있는 이터레이터 메서드가 있습니다. 예를 들어, each
, map
, select
와 같은 메서드를 통해 쉽게 요소를 순회하고 조작할 수 있습니다.
fruits = ["사과", "바나나", "체리"] fruits.each do |fruit| puts fruit end squared_numbers = [1, 2, 3, 4].map { |n| n ** 2 } puts squared_numbers.inspect
위의 코드에서 each
메서드를 사용하여 과일 목록을 출력하고, map
메서드를 사용하여 숫자의 제곱을 계산하여 새로운 배열을 생성합니다. 이처럼 루비의 내장 이터레이터를 사용하면 코드 작성이 훨씬 간편해집니다.
이번 글에서는 루비에서 이터레이터 패턴을 구현하는 방법에 대해 알아보았습니다. 이터레이터 패턴은 컬렉션의 내부 구조를 숨기고, 요소를 순차적으로 접근할 수 있는 방법을 제공합니다. 기본적인 이터레이터 구현부터 발전된 이터레이터까지 살펴보았으며, 루비의 내장 이터레이터도 소개했습니다.
이러한 이터레이터 패턴을 활용하면 코드의 가독성과 재사용성을 높일 수 있으며, 다양한 데이터 구조를 일관되게 다룰 수 있습니다. 앞으로 루비를 사용할 때 이터레이터 패턴을 적극적으로 활용해 보시기 바랍니다.
```© 2024 RailsInsights. All rights reserved.