2011년 5월 23일 월요일

The Iterator Pattern

16. The Iterator Pattern
Iterator 는 디자인 패턴에서 가장 간단하고 가장 빈번하게 사용되는 패턴들 중의 하나이다. Iterator 패턴은 데이터의 내부적인 표현을 자세하게 아는 것 없이 표준적인 인터페이스를 이용한 데이터의 리스트나 컬렉션을 통하여 이동하는 것을 허용한다. 게다가 어떤 특별한 프로세싱과 데이터 컬렉션의 특정한 원소를 반환을 하는 특별한 Iterator를 정의할 수 있다.

구조
*


역할
  • Iterator – 요소를 차례로 스캔할 인터페이스(API)를 결정한다.
  • ConcreteIterator – Iterator 에서 정한 인터페이스(API)를 실제로 구현한다.
  • Aggregate – Iterator 역할을 만들어내는 인터페이스(API)를 제공한다.
  • ConcreteAggregate – Aggregate 역할이 정한 인터페이스(API)를 실제로 구현한다.


의도
집합object의 원소들의 내부형태를 알필요없이 해당 원소에 접근 가능하게 해준다.

적용시기
  • 집합object의 내부 구조를 알 필요없이 접근 하고 싶을때
  • 집합object를 다양한 방법으로 이동하고 싶을 때
  • 여러가지 집합object를 이동할 수 있는 통합 interface를 원할 때. (polymorphic iteration)


결론
  • 테이터 수정 – Iterator 사용에 따른 가장 중요한 질문은 수정할 때 데이터의 반복을 고려한다는 것이다. 만약 코드가 광범위하고 경우에 따라서 다음 요소로 이동한다면, 요소는 이동하는 동안 기본적인 컬렉션에서 추가되거나 삭제된다. 또한 또 다른 쓰레드가 그 컬렉션을 바꿀 수 있다. 이 문제에 대한 간단한 솔루션은 없다. 루프를 선언해서 안전한 Enumeration 쓰레드를 만들어 동기화할 수 있다. 그러나 Enumeration 을 사용해서 루프로 이동하거나 특정 아이템을 삭제하려고 한다면 유념해야 한다. 요소를 삭제하거나 추가하는 것은 사용하고 있는 저장 메커니즘에 따라서 특정 요소를 건너뛰거나 두 번 액세스한다는 것을 의미한다.
  • 허가된 접근(Privileged access) – Enumeration 클래스는 원래의 컨테이너 클래스의 기본적인 구조에 일종의 허가된 접근을 할 필요가 있다. 따라서 Enumeration 클래스는 데이터로 이동할 수 있다. 만약 데이터가 vector 나 Hashtable 에 저장 되어있다면, 이렇게 실행하는 것은 아주 쉽다. 그러나 데이터가 클래스 안에 다른 컬렉션 구조라면, 아마도 get 연산으로 그 구조를 실행 할 수 있도록 해야 할 것 이다.
  • 외부 Iterator 와 내부 Iterator – 디자인 패턴은 두 가지 종류의 Iterator 를 설명한다. 하나는 외부 Iterator 이고, 다른 하나는 내부 Iterator 이다. 지금가지는 외부 Iterator 에 대해서만 이야기 하였다. 내부 Iterator 는 사용자의 특별 요청없이 각각의 요소에 직접적으로 연산을 샐행하면서 전체 컬렉션으로 이동하는 메소드이다. 내부 Iterator 는 java 에서 외부 Iterator 보다 일반적이지 못하다. 그러나 0에서 1 사이에 놓는 데이터값의 컬렉션을 정규화하거나 모든 문자열을 특정 활자로 변환하는 메소드가 가능하다.
    자바 언어에서의 Enumeration
    Enumeration 유현은 Vector와 Hashtable 클래스로 구현된다. 이들은 Enumeration 유형의 두가지 메소드를 직접적으로 구현하는 클래스라기 보다는 해당 클래스의 데이터에 대한 Enumeration을 반환하는 elements 메소드를 포함하는 클래스라 할 수 있다.


    예제소스
    이 프로그램은 왼쪽에 (50free.txt)파일에 등록된 모든 아이들을 표시하고, 클럽 리스트로 콤보 박스를 체운다. 그런 다음 사용자가 클럽을 선택하면 우측리스트에는 클럽에 소속된 아이들만 표시한다.
    예제 소스
    import java.util.*;
    public class Kid {
    String frname, lname, club;
    int age;
    float time;
    public Kid(String line) {
    StringTokenizer tok = new StringTokenizer(line);
    String lnum = tok.nextToken();
    frname=tok.nextToken();
    lname = tok.nextToken();
    age = new Integer(tok.nextToken()).intValue();
    club = tok.nextToken();
    time = new Float(tok.nextToken()).floatValue();
    }
    public int getAge() { return age;}
    public float getTime() {return time;}
    public String getFrname() {return frname;}
    public String getLname(){return lname;}
    public String getClub() {return club;}
    }
    import java.util.*;
    public class kidClub implements Enumeration {
    private String clubMask;
    private Kid kid;
    private Enumeration ke;
    private KidData kdata;
    public kidClub(KidData kd, String club) {
    clubMask = club;
    kdata = kd;
    kid = null;
    ke = kdata.elements();
    }
    public boolean hasMoreElements() {
    boolean found = false;
    while (ke.hasMoreElements() && ! found) {
    kid = (Kid)ke.nextElement();
    found = kid.getClub().equals(clubMask);
    }
    if (! found)
    kid = null;
    return found;
    }
    public Object nextElement() {
    if (kid != null)
    return kid;
    else
    throw new NoSuchElementException();
    }
    }
    import java.util.*;
    public class KidData {
    private Vector kids;
    private Hashtable clubs;
    public KidData(String filename) {
    kids = new Vector();
    clubs = new Hashtable();
    InputFile f = new InputFile(filename);
    String s = f.readLine();
    while (s != null) {
    if (s.trim().length() > 0) {
    Kid k = new Kid(s);
    kids.addElement(k);
    clubs.put (k.getClub (), k.getClub ());
    }
    s = f.readLine();
    }
    }
    public String[] getClubs() {
    String s[] = new String[clubs.size ()];
    Enumeration enum = clubs.elements ();
    int max = clubs.size();
    for (int i=0; i < max; i++)
    s[i] = (String)enum.nextElement ();
    for (int i=0; i<max; i++) {
    for (int j=i; j<max; j++) {
    if ((s[i].compareTo (s[j]) > 0)) {
    String tmp = s[i];
    s[i] = s[j];
    s[j] = tmp;
    }
    }
    }
    return s;
    }
    public Kid[] getData() {
    Kid[] kd = new Kid[kids.size()];
    for (int i=0; i< kids.size(); i++)
    kd[i] = (Kid)kids.elementAt(i);
    return kd;
    }
    public Enumeration elements() {
    return kids.elements();
    }
    public Enumeration kidsInClub(String club) {
    return new kidClub(this, club);
    }
    public int size() {
    return kids.size();
    }
    public Kid getKid(int i) {
    return(Kid)kids.elementAt(i);
    }
    }
    public interface awtList {
    public void add(String s);
    public void remove(String s);
    public String[] getSelectedItems();
    }
    import java.awt.*;
    import java.io.*;
    public class InputFile {
    RandomAccessFile f = null;
    boolean errflag;
    String s = null;
    public InputFile(String fname) {
    errflag = false;
    try {
    f = new RandomAccessFile(fname, "r");
    } catch (IOException e) {
    System.out.println("no file found");
    errflag = true; //and set flag
    }
    }
    public boolean checkErr() {
    return errflag;
    }
    public String read() {
    String ret = "";
    if (s == null) {
    s = readLine();
    }
    if (s != null) {
    s.trim();
    int i = s.indexOf(",");
    if (i <= 0) {
    ret = s.trim();
    s = null;
    } else {
    ret = s.substring(0, i).trim();
    s = s.substring(i+1);
    }
    } else {
    ret = null;
    }
    return ret;
    }
    public String readLine() {
    s = null;
    try {
    s = f.readLine();
    } catch (IOException e) {
    errflag = true;
    System.out.println("File read error");
    }
    return s;
    }
    public void close() {
    try {
    f.close();
    } catch (IOException e) {
    System.out.println("File close error");
    errflag = true;
    }
    }
    }
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.text.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.border.*;
    public class JawtList extends JScrollPane
    implements ListSelectionListener, awtList {
    private JList listWindow;
    private JListData listContents;
    public JawtList(int rows) {
    listContents = new JListData();
    listWindow = new JList(listContents);
    listWindow.setPrototypeCellValue("Abcdefg Hijkmnop");
    getViewport().add(listWindow);
    }
    public void add(String s) {
    listContents.addElement(s);
    }
    public void remove(String s) {
    listContents.removeElement(s);
    }
    public void clear() {
    listContents.clear();
    }
    public String[] getSelectedItems() {
    Object[] obj = listWindow.getSelectedValues();
    String[] s = new String[obj.length];
    for (int i =0; i<obj.length; i++)
    s[i] = obj[i].toString();
    return s;
    }
    public void valueChanged(ListSelectionEvent e){}
    }
    class JListData extends AbstractListModel {
    private Vector data;
    public JListData() {
    data = new Vector();
    }
    public int getSize() {
    return data.size();
    }
    public Object getElementAt(int index) {
    return data.elementAt(index);
    }
    public void addElement(String s) {
    data.addElement(s);
    fireIntervalAdded(this, data.size()-1, data.size());
    }
    public void removeElement(String s) {
    data.removeElement(s);
    fireIntervalRemoved(this, 0, data.size());
    }
    public void clear() {
    int size= data.size();
    data = new Vector();
    fireIntervalRemoved(this, 0, size);
    }
    }
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.text.*;
    import javax.swing.*;
    import javax.swing.event.*;
    public class JxFrame extends JFrame {
    public JxFrame(String title) {
    super(title);
    setCloseClick();
    setLF();
    }
    private void setCloseClick() {
    addWindowListener(
    new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    System.exit(0);
    }
    }
    );
    }
    private void setLF() {
    String laf = UIManager.getSystemLookAndFeelClassName();
    try {
    UIManager.setLookAndFeel(laf);
    } catch (UnsupportedLookAndFeelException exc) {
    System.err.println("Warning: UnsupportedLookAndFeel: " + laf);
    } catch (Exception exc) {
    System.err.println("Error loading " + laf + ": " + exc);
    }
    }
    }
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Enumeration;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JPanel;
    import javax.swing.border.EmptyBorder;
    public class IterDemo extends JxFrame implements ActionListener {
    JawtList kidList, kidClubList;
    JComboBox clubs;
    JButton Get;
    KidData kdata;
    public IterDemo() {
    super("Iterator 패턴 데모");
    JPanel jp = new JPanel();
    getContentPane().add(jp);
    jp.setLayout(new GridLayout(1,2));
    JPanel left = new JPanel();
    JPanel right = new JPanel();
    jp.add(left);
    jp.add(right);
    left.setBorder(new EmptyBorder(5,5,5,5));
    right.setBorder(new EmptyBorder(5,5,5,5));
    kidList = new JawtList(20);
    left.setLayout(new BorderLayout());
    left.add("Center", kidList);
    right.setLayout(new BorderLayout());
    Get = new JButton("Get");
    Get.addActionListener(this);
    JPanel rtop = new JPanel();
    right.add ("North", rtop);
    kdata = new KidData ("50free.txt");
    fillKidList();
    clubs = new JComboBox(kdata.getClubs ());
    rtop.add(clubs);
    rtop.add(Get);
    kidClubList = new JawtList(20);
    right.add("Center",kidClubList);
    setSize(new Dimension(400,300));
    setVisible(true);
    }
    private void fillKidList() {
    Enumeration ekid = kdata.elements();
    while (ekid.hasMoreElements()) {
    Kid k =(Kid)ekid.nextElement();
    kidList.add(k.getFrname()+" "+k.getLname());
    }
    }
    public void actionPerformed(ActionEvent e) {
    String club = (String)clubs.getSelectedItem();
    kidClubList.clear ();
    if(club.trim().length() > 0) {
    Enumeration eclub = new kidClub(kdata, club);
    while(eclub.hasMoreElements()) {
    Kid k =(Kid)eclub.nextElement();
    kidClubList.add(k.getFrname()+" "+k.getLname());
    }
    }
    }
    static public void main(String argv[]) {
    new IterDemo();
    }
    }
    à 50free.txt
    1 Amanda McCarthy 12 WCA 29.28
    2 Jamie Falco 12 HNHS 29.80
    3 Meaghan O'Donnell 12 EDST 30.00
    4 Greer Gibbs 12 CDEV 30.04
    5 Rhiannon Jeffrey 11 WYW 30.04
    6 Sophie Connolly 12 WAC 30.05
    7 Dana Helyer 12 ARAC 30.18
    8 Lindsay Marotto 12 OAK 30.23
    9 Sarah Treichel 12 WYW 30.35
    10 Ashley McEntee 12 RAC 30.47
    11 Rachel Brookman 12 CAT 30.51
    12 Michelle Ducharme 12 LEHY 30.51
    13 Karleen Danais 12 NES 30.70
    14 Megan Loock 12 WAC 30.90
    15 Kaitlyn Ament 12 HNHS 30.93
    16 Tara Schoen 12 WYW 31.01
    17 Kate Olshefski 12 NCY 31.01
    18 Emma Zuidema 12 HMST 31.07
    19 Katie Persing 12 OAK 31.14
    20 Christina Monsees 11 RAC 31.27
    21 Kimberly Watcke 12 CDEV 31.50
    22 Colleen Smith 12 AJSC 31.52
    23 Chloe Osborne 12 GYWD 31.74
    24 Natalia Fugate 12 WAC 31.75
    25 Lisa McHale 11 RAC 31.76
    26 Lindsay Cowles 11 NES 31.79
    27 Jacquelyn Yavarone 12 HNHS 31.83
    28 Molly Fenn 12 WRAT 31.84
    29 Karin Brudvig 12 HMST 31.84
    30 Annie Duffy 12 MGAT 31.90
    31 Nicole Coia 11 WCA 31.94
    32 Elizabeth Rice 12 WYW 31.96
    33 Yvette Landwehr 12 WRAT 32.00
    34 Ashley Recklet 12 SHEL 32.24
    35 Lauren McKenna 11 PSDY 32.27
    36 Kristen Fontaine 12 EDST 32.28
    37 Diana Cooke 12 ZEUS 32.33
    38 Kimberly Gambino 11 NES 32.43
    39 Jenny Morgan 11 NES 32.49
    40 Colleen Coelho 12 CDEV 32.50
    41 Leigh Gordon 12 CDEV 32.62
    42 Caitlin Gillen 12 WYW 32.75
    43 Kristen Skroski 12 HNHS 32.91
    44 Sarah Greenberg 11 CDEV 32.97
    45 Kathy Collins 12 EHBB 33.11
    46 Morgan Bullock 12 ICSC 33.33
    47 Brittany Medlin 12 CAT 33.33
    48 Haley Ottenbreit 12 HNHS 33.35
    49 Laura Kunces 11 WAC 33.64
    50 Hayley Wolfgruber 12 WYW 33.73
    51 Katie Duffy 12 MGAT 34.24


    관련패턴
    • Composite Pattern: Iterator는 종종 Composite의 recursive구조접근에 응용됨
    • FactoryMethod Pattern: Polymorphic Iterator들은 적절한 Iterator subclass의 object를 만드는 데 사용됨

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...