Design pattern/행동 패턴

[디자인 패턴] 14장 반복자 패턴

미스터로즈 2021. 5. 19. 12:09

공부하기 위해서 요약정리해놓은 것입니다..

 

정확하고 꼼꼼한 자료는 쉽게 배워 바로 써먹는 디자인 패턴을 확인하시고

코드는 github.com/infohojin/patterns 을 참고해 주세요.

 

반복자 패턴은 내부 구조를 노출하지 않고 집합체를 통해 원소 객체에 순차적으로 접근할 수 있는 방법을 제공합니다.

 

객체의 집합

집합은 어떤 조건에 의해 모인 요소의 묶음입니다. 객체의 데이터 또는 기능을 집합으로 묶어 처리할 수 있습니다.

 

배열은 유사한 조건의 데이터를 하나의 집합으로 묶어서 처리합니다.

$fruit = ['apple','banana','berry'];

 

배열의 특징은 하나의 변수명을 사용해 여러 데이터를 저장한다는 것입니다.

PHP와 같은 동적 데이터를 저장하는 언어에서는 배열에 문자열뿐만 아니라 다양한 종류의 데이터 타입을 저장할 수 있습니다.

 

하나의 배열은 복수의 데이터를 가집니다. 즉, 데이터를 그룹화합니다. 배열 각각의 요소는 색인을 이용해 접근하며 각 색인은 숫자 또는 키 값을 이용해 접근합니다.

 

배열

배열은 집합 개념을 이해하는데 도움이 됩니다.

집합은 여러 개의 데이터를 하나로 묶습니다. 반복자 패턴에서는 객체로 묶인 요소들을 관리하고 실행합니다.

 

선언된 클래스는 인스턴스화를 통해 객체로 생성되고, 생성된 여러 객체들은 배열로 묶어 관리합니다.

 

요소를 하나의 집합으로 묶으면 각각의 요소는 순서를 가집니다. 이 순서는 색인 또는 키를 통해 묶을 수 있습니다. 순차적으로 묶인 배열은 인덱스 번호를 통해 접근합니다.

 

순환은 모든 요소에 하나씩 접근하여 실행하는 것을 말합니다. 배열이 여러 개의 객체를 가진 경우 각각의 객체에 접근해서 사용합니다.

 

<?php

require_once "Fruit.php";

$fruit = [
    new Fruit("Apple"),
    new Fruit("Banana"),
    new Fruit("Berry"),
    new Fruit("Grape")
];

for ($i=0; $i<count($fruit);$i++) {
    echo $fruit[$i]->getName()."\n";
}

반복자는 객체에 순차적으로 접근하여 처리를 수행하는 동작과 유사합니다.

 

집합체

반복자는 객체의 효율적인 집합 관리를 위해 별도의 집합체를 갖고 있습니다.

 

집합체는 단순 배열과 달리 복수의 객체를 가진 복합 객체입니다. 집합체를 다른 말로 컬렉션이라고 합니다.

 

반복자 패턴은 배열을 사용하지 않고 별도의 컬렉션 객체를 생성합니다. 컬렉션 객체로 설계하는 이유는 패턴으로서 효율적으로 객체를 관리하기 위해서입니다.

 

<?php
/**
 * 컬렉션
 */
class Collection implements Aggregate
{
    // 외부의 직접수정을 방지합니다.
    private $objs = [];
    private $last = 0;

    /**
     * 집합에서 하나의 객체를 반환합니다.
     */
    public function getObj($id)
    {
        return $this->objs[$id];
    }

    /**
     * 전체 객체의 갯수를 반환합니다.
     */
    public function getLast()
    {
        return $this->last;
    }

    /**
     * 새로운 객체를 추가합니다.
     */
    public function append($obj)
    {
        array_push($this->objs, $obj);
        $this->last++;
    }

    /**
     * 인터페이스 구현
     */
    public function iterator()
    {
        // 이터레이터 객체를 생성합니다.
        return new IteratorObject($this);
    }
}

컬렉션으로 묶은 각각의 객체는 요소입니다. 컬렉션은 append() 메서드가 전달한 객체를 내부의 $objs 배열에 저장합니다.

 

객체를 추가하는 경우 객체의 $last값을 1씩 증가시킵니다.

컬렉션은 순환하는 객체를 가진 단순한 묶음의 객체입니다.

 

컬렉션은 복수의 객체를 가진 집합체로, 내부 객체의 반복 순환을 처리하기 위해 동작을 분리합니다. 분리된 제어부는 필요에 따라 내부 또는 외부에 위치할 수 있습니다. 외부 반복자는 사용자가 반복 제어를 직접 결정하고, 내부 반복자는 내부 제어를 반복자가 처리합니다.

반복자

반복자는 묶여 있는 객체들에 순차적으로 접근하여 처리할 수 있는 로직들을 제공합니다. 또한, 컬렉션 안에 있는 객체를 순환 반복하기 위해 외부 반복자를 분리하여 설계합니다.

 

반복자 패턴이 객체를 순환 처리하기 위해서는 몇 가지 메서드가 필요합니다. 설계 시 메서드의 생성 의무를 부여하는 인터페이스를 선언합니다.

 

반복자를 설계할 때는 반복 개념을 일반화하여 다형성을 추가하는 것이 중요합니다. 실습을 위해 인터페이스를 추가로 설계하겠습니다.

 

<?php

interface PloyIterator
{
    public function isNext();
    public function next();
}

선언한 PloyIterator 인터페이스를 적용하여 반복 객체를 선언합니다. 반복 객체는 몇 가지 제어 메서드를 필요로 하므로 함께 구현합니다.

<?php
/**
 * 집합체: 이터레이터
 */
class IteratorObject implements PloyIterator
{
    private $Aggregate;
    private $index = 0;

    public function __construct($agg)
    {
        $this->Aggregate = $agg;
    }

    public function isNext()
    {
        if ($this->index >= $this->Aggregate->getLast()) {
            return false;
        } else {
            return true;
        }
    }

    public function next()
    {
        $obj = $this->Aggregate->getObj($this->index);
        $this->index++;
        return $obj;
    }
}

반복 객체는 컬렉션에 저장된 객체를 순환하도록 객체를 반환하는 역활을 합니다.

 

반복자의 객체 생성은 집합 객체에 의해 이루어집니다. 따라서 반복자는 집합 객체와 의존 관계를 가집니다.