본문 바로가기
Study/디자인 패턴

[C#/Unity][디자인패턴] 반복자 패턴(Iterator Pattern)

by 스테디코디스트 2023. 12. 16.
반응형

1. 반복자 패턴이란?

- 일련의 데이터 집합에 대해 순차적인 접근(순회)을 지원하는 패턴.

- 컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 접근할 수 있는 방법을 제공하는 패턴.

- 반복자를 사용하여 컨테이너를 가로지르며 컨테이너의 요소들에 접근하는 디자인 패턴.

- 컬렉션의 요소들을 순회하는 패턴.

 

2. 반복자 패턴을 사용하는 경우

- 해시나 트리구조와 같이 저장순서가 정해지지 않고 적재된 데이터들을 순회하는 방법을 정하는 경우

- 컬렉션에 상관없이 객체 접근 순회 방식을 통일하고자 할 경우

- 컬렉션을 순회하는 다양한 방법을 지원하고 싶은 경우

- 컬렉션의 복잡한 내부 구조를 클라이언트로부터 숨기고 싶은 경우(편의 + 보안)

- 데이터 저장 컬렉션 종류가 변경 가능성이 있는 경우

 

3. 반복자 패턴의 장점

1) 일관성 - 일관된 이터레이터 인터페이스를 사용해 여러 형태의 컬렉션에 대해 동일한 순회 방법을 제공함.

2) 은닉성 - 컬렉션의 내부 구조 및 순회 방식을 알지 않아도 됨.

3) 분리성 - 집합체의 구현부와 처리부를 반복자 객체로 분리해 결합도를 줄일 수 있음.

4) 단일 책임 원칙(SRP) 준수 - 순회 알고리즘을 별도의 반복자 객체에 추출하여 각 클래스의 책임을 분리하여 SRP를 준수한다.

5) 개방 폐쇄 원칙(OCP) 준수 - 데이터 저장 컬렉션 종류가 변경되어도 클라이언트 구현 코드는 손상되지 않아 수정에는 닫혀있어 OCP를 준수한다.

 

4. 반복자 패턴의 단점

1) 클래스가 늘어나고 복잡도가 증가한다.

2) 구현 방법에 따라 캡슐화를 위배할 수 있다.

3) 내부 표현을 노출시키면 컬렉션의 종류가 바뀔 때마다 클라이언트 코드를 변경해주어야 함.

 

5. 코드 구현

- 구조

1) Aggregate(인터페이스)

- Concrete Iterator 객체를 반환하는 인터페이스 제공

2) Concrete Aggregate(클래스)

- 여러 요소들이 이루어져 있는 데이터들의 집합

3) Iterator(인터페이스)

- Concrete Iterator 객체를 만듬

- 집합체 내의 요소들을 순서대로 검색하기 위한 인터페이스 제공

4) Concrete Iterator(클래스)

- 반복자 객체

- concrete Aggregate가 구현한 메서드로부터 생성되며, Concrete Aggregate의 컬렉션을 참조하여 순회함

 

- 코드 구현(C#)

1) 패턴 적용 전

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace StudyCSharp
{
    // 공부
    class Study
    { 
        // 과목명
        string _name;
        public string Name {  get { return _name; } }

        // 흥미도(10점 만점)
        int _interest; 
        public int Interest { get { return _interest; } }

        // 마지막 공부일자 - 오늘 날짜 23.12.15 기준
        DateTime _lastTime; 
        public DateTime LastTime { get { return _lastTime; } }

        public Study(string name, int interest, DateTime lastTime)
        {
            this._name = name;
            this._interest = interest;
            this._lastTime = lastTime;
        }
    }

    // 시간표
    class TimeTable
    {
        List<Study> studyList = new List<Study>(); // 공부목록

        public void addStudy(string name, int interest, DateTime lastTime)
        {
            this.studyList.Add(new Study(name, interest, lastTime));
        }

        public List<Study> getStudyList()
        {
            return studyList;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 시간표 생성
            TimeTable timeTable = new TimeTable();

            // 시간표 목록 작성
            timeTable.addStudy("국어", 3, new DateTime(2023, 12, 12));
            timeTable.addStudy("수학", 8, new DateTime(2023, 12, 14));
            timeTable.addStudy("체육", 10, DateTime.Today);
            timeTable.addStudy("영어", 4, new DateTime(2023, 12, 11));
            timeTable.addStudy("과학", 9, new DateTime(2023, 12, 13));

            // 시간표 저장
            List<Study> studyList = timeTable.getStudyList();

            // 시간표 작성 순으로 조회
            for (int i = 0; i < studyList.Count; i++)
            {
                Study study = studyList[i];
                Console.WriteLine(study.Name + " / " + study.Interest + " / " + study.LastTime);
            }
            
            Console.WriteLine("----------------------------------------------");

            // 흥미 낮은순으로 시간표 정렬
            List<Study> InterestOrderList = studyList.OrderBy(i => i.Interest).ToList();

            // 흥미 순으로 시간표 조회
            for (int i = 0; i < InterestOrderList.Count; i++)
            {
                Study study = InterestOrderList[i];
                Console.WriteLine(study.Name + " / " + study.Interest + " / " + study.LastTime);
            }

            Console.WriteLine("----------------------------------------------");

            // 마지막에 공부한 과목부터 차례로 시간표 정렬
            List<Study> TimeOrderList = studyList.OrderByDescending(i => i.LastTime).ToList();

            // 시간 순으로 시간표 조회
            for (int i = 0; i < TimeOrderList.Count; i++)
            {
                Study study = TimeOrderList[i];
                Console.WriteLine(study.Name + " / " + study.Interest + " / " + study.LastTime);
            }

            Console.WriteLine("----------------------------------------------");
        }
    }
}

 

- 실행 결과

 

2) 패턴 적용 후

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace StudyCSharp
{
    abstract class Aggregate
    {
        public abstract Iterator CreateIterator();
    }

    abstract class Iterator
    {
        public abstract Study First();
        public abstract Study Next();
        public abstract Study CurrentItem();
        public abstract bool IsDone();

    }    

    // Data Type
    class Study
    {
        // 과목명
        string _name;
        public string Name { get { return _name; } }

        // 흥미도(10점 만점)
        int _interest;
        public int Interest { get { return _interest; } }

        // 마지막 공부일자 - 오늘 날짜 23.12.16 기준
        DateTime _lastTime;
        public DateTime LastTime { get { return _lastTime; } }

        public Study(string name, int interest, DateTime lastTime)
        {
            this._name = name;
            this._interest = interest;
            this._lastTime = lastTime;
        }
    }

    // Concrete Aggregate
    class TimeTable : Aggregate
    {
        private List<Study> _timeTable = new List<Study> (); // 공부 목록

        public void addTimeTable (string name, int interest, DateTime lastTime)
        {
            // 리스트에 항목 추가
            this._timeTable.Add(new Study(name, interest, lastTime));
        }

        public List<Study> getTimeTable()
        {
            // 리스트를 불러옴
            return _timeTable;
        }

        public void setTimeTable(List<Study> timeTable)
        {
            _timeTable = timeTable;
        }

        public override Iterator CreateIterator()
        {
            return new SortIterator(this);
        }

        public int Count
        {
            get { return _timeTable.Count; }
        }

        public Study this[int index]
        {
            get { return _timeTable[index]; }
            set { _timeTable.Insert(index, value); }
        }
    }

    // Concrete Iterator
    class SortIterator : Iterator
    {
        protected TimeTable _timeTable = new TimeTable();
        private int _current = 0;

        public SortIterator(TimeTable timeTable)
        {
            this._timeTable = timeTable;
        }

        public void IntersetIterator(TimeTable timeTable)
        {
            // 흥미를 기준으로 TimeTable을 정렬
            this._timeTable.setTimeTable(timeTable.getTimeTable().OrderBy(i => i.Interest).ToList());
        }

        public void DateIterator(TimeTable timeTable)
        {
            // 날짜를 기준으로 TimeTable 정렬
            this._timeTable.setTimeTable(timeTable.getTimeTable().OrderBy(i => i.LastTime).ToList());
        }

        public override Study First()
        {
            return _timeTable[0];
        }

        public override Study Next()
        {
            Study ret = null;

            if (_current < _timeTable.Count - 1)
            {
                ret = _timeTable[++_current];
            }

            return ret;
        }

        public override Study CurrentItem()
        {
            return _timeTable[_current];
        }

        public override bool IsDone()
        {
            return _current >= _timeTable.Count;
        }
    }

    // Concrete Iterator
    class InterestIterator : SortIterator
    {
        public InterestIterator(TimeTable timeTable) : base(timeTable)
        {
            // 흥미를 기준으로 TimeTable을 정렬
            this._timeTable.setTimeTable(timeTable.getTimeTable().OrderBy(i => i.Interest).ToList());
        }
    }

    // Concrete Iterator
    class DateIterator : SortIterator
    {
        public DateIterator(TimeTable timeTable) : base(timeTable)
        {
            // 날짜를 기준으로 TimeTable 정렬
            this._timeTable.setTimeTable(timeTable.getTimeTable().OrderByDescending(i => i.LastTime).ToList());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 시간표 생성
            TimeTable timeTable = new TimeTable();

            // 시간표 목록 작성
            timeTable.addTimeTable("국어", 3, new DateTime(2023, 12, 12));
            timeTable.addTimeTable("수학", 8, new DateTime(2023, 12, 14));
            timeTable.addTimeTable("체육", 10, DateTime.Today);
            timeTable.addTimeTable("영어", 4, new DateTime(2023, 12, 11));
            timeTable.addTimeTable("과학", 9, new DateTime(2023, 12, 13));

            // 흥미 기준 정렬
            SortIterator interestiter = new InterestIterator(timeTable);

            foreach (Study s in timeTable.getTimeTable())
            {
                Console.WriteLine(s.Name + " / " + s.Interest + " / " + s.LastTime);
            }

            Console.WriteLine("----------------------------------------------");

            // 날짜 기준 정렬(시간이 가까운 순)
            SortIterator dateiter = new DateIterator(timeTable);

            foreach(Study s in timeTable.getTimeTable())
            {
                Console.WriteLine(s.Name + " / " + s.Interest + " / " + s.LastTime);
            }

            Console.WriteLine("----------------------------------------------");
        }
    }    
}

 

- 실행 결과


<참고 사이트>

 

[C# 디자인패턴] 제14강 이터레이터(반복자) 패턴

예제코드123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105using System;using System.Collections

codepump.tistory.com

 

💠 반복자(Iterator) 패턴 - 완벽 마스터하기

Iterator Pattern 반복자(Iterator) 패턴은 일련의 데이터 집합에 대하여 순차적인 접근(순회)을 지원하는 패턴이다. 데이터 집합이란 객체들을 그룹으로 묶어 자료의 구조를 취하는 컬렉션을 말한다.

inpa.tistory.com

 

이터레이터 패턴 (Iterator Pattern) 이란?

이터레이터 패턴 (Iterator Pattern) 이란? 컬렉션의 요소를 순회하는 패턴이다. 내부의 표현을 노출시키지 않는다. List, Stack, Tree, Set 과 같이 어떠한 컬렉션인지 노출시키지 않는다. 내부 표현을 노

jake-seo-dev.tistory.com

 

 

반복자 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 반복자 패턴(iterator pattern)은 객체 지향 프로그래밍에서 반복자를 사용하여 컨테이너를 가로지르며 컨테이너의 요소들에 접근하는 디자인 패턴이다. 반복자 패

ko.wikipedia.org

 

[Design Pattern] 이터레이터 패턴 (iterator pattern)

행위(Behavioral) 패턴컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체안에 들어있는 모든 항목에 접근할 수 있게 해 주는 방법을 제공해 주는 패턴이터레이터 패턴을 사용하면 집합체 내에

velog.io

 

이터레이터 패턴 (iterator pattern)

이터레이터 패턴 (iterator pattern) 컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 접근할 수 있는 방법을 제공한다. 컬렉션 객체 안에 들어있는 모든 항목에 접

jusungpark.tistory.com