글 검색

공개된 글의 제목과 본문을 검색합니다.

    닫기 Esc

    반복자 패턴 (Iterator Pattern)#

    • 반복자 패턴은 컬럭션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공하는 패턴
    • 이 패턴을 사용하면 집합체 내에서 어떤 식으로 일이 처리되는지 전혀 모르는 상태에서 그 안에 들어있는 모든 항목을 대상으로 반복 작업을 수행할 수 있음
    • 반복자 패턴을 사용하면 모든 항목에 일일이 접근하는 작업을 컬럭션 객체가 아닌 반복자 객체가 맡게 됨
      • 집합체의 인터페이스와 구현이 간단해지고 집합체 반복 작업에서 손을 떼고 원래 자신이 할 일에만 전념할 수 있음

    단일 역할 원칙#

    • 어떤 클래스가 바뀌는 이유는 하나뿐이어야 한다.
    • 클래스를 고치는 일은 최대한 피해야 함
      • 코드를 변경할 만한 이유가 2가지나되면 그 만큼 그 클래스를 고쳐야할 가능성이 커지며 디자인에 있어서 2가지 부분에 영향을 미치게 됨

    객체마을 식당 메뉴에 반복자 추가하기#

    • 객체마을 식당과 팬케이크 하우스가 합병되어 메뉴 구현항목이 서로 다르다는 문제점이 발생
      • 한쪽은 배열로, 한쪽은 ArrayList 컬렉션을 사용 함
    java
    public interface Iterator {
    		boolean hasNext();
    		MenuItem next();
    }
    
    public interface Menu {
    		Iterator createIterator();
    }
    메뉴의 반복을 캡슐화한 반복자 인터페이스
    java
    public class DinerMenuIterator implements Iterator {
    		MenuItem[] items;
    		int position = 0;
    	 
    		public DinerMenuIterator(MenuItem[] items) {
    				this.items = items;
    		}
    	 
    		public MenuItem next() {
    				MenuItem menuItem = items[position];
    				position = position + 1;
    				return menuItem;
    		}
    	 
    		public boolean hasNext() {
    				if (position >= items.length || items[position] == null) {
    					return false;
    				} else {
    					return true;
    				}
    		}
    }
    DinerMenu 클리스에 사용할 구상 Iterator 클래스
    java
    public class DinerMenu implements Menu {
    		static final int MAX_ITEMS = 6;
    		int numberOfItems = 0;
    		MenuItem[] menuItems;
    	
    	  // 생성자
    	
    		// addItem 호출
    	
    		@Override
    		public Iterator createIterator() {
    				return new DinerMenuIterator(menuItems);
    		}
    	 
    		// 기타 메뉴 관련 메소드
    }
    반복자 패턴의 구상 클래스를 리턴하도록 변경
    java
    public class Waitress {
    		...
    		private void printMenu(Iterator iterator) {
    				while (iterator.hasNext()) {
    						MenuItem menuItem = iterator.next();
    						System.out.print(menuItem.getName() + ", ");
    						System.out.print(menuItem.getPrice() + " -- ");
    						System.out.println(menuItem.getDescription());
    				}
    		}
    		...
    }
    하나의 반복자로 모든 메뉴를 출력할 수 있음!

    Iterable 인터페이스 알아보기#

    • 어떤 클래스에서 Iterable을 구현한다면 그 클래스는 iterator() 메소드를 구현해야 함
    • 그 메소드는 Iterator 인터페이스를 구현하는 반복자를 리턴함
    • 이 인터페이스에는 컬렉션이 있는 항목을 대상으로 반복 작업을 수행하는 방법을 제공하는 forEach() 메소드가 기본으로 포함 됨
    • 자바는 향상된 for 순황문으로 몇 가지 편리한 문법적 기능을 제공함
    java
    public class Waitress {
    		...
    		private void printMenu(Iterator iterator) {
    				for (MenuItem item : iterator) {
    						System.out.print(menuItem.getName() + ", ");
    						System.out.print(menuItem.getPrice() + " -- ");
    						System.out.println(menuItem.getDescription());
    				}
    		}
    		...
    }
    hasNext, next 메소드를 직접 사용하지 않아도 됨

    컴포지트 패턴 (Composite)#

    • 컴포지트 패턴으로 객체를 트리구조로 구성해서 부분-전체 계층구조를 구현합니다.
    • 컴포지트 패턴을 사용하면 클라이언트에서 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있음
    • 메뉴와 항목을 같은 구조에 넣어서 부분-전체 계증 구조를 생성할 수 있음
    • 컴포지트 패턴을 사용하면 객체의 구성와 개별 객체를 노드로 가지는 트리 형태의 객체 구조를 만들 수 있음
    • 이런 복합구조를 사용하면 복합 객체와 개별객체를 대상으로 똑같은 작업을 적용할 수 있음
    • 즉, 복합 객체와 개별 객체를 구분할 필요가 거의 없어짐
    java
    public abstract class MenuComponent {
    		public void add(MenuComponent menuComponent) {
    				throw new UnsupportedOperationException();
    		}
    		public void remove(MenuComponent menuComponent) {
    				throw new UnsupportedOperationException();
    		}
    		public MenuComponent getChild(int i) {
    				throw new UnsupportedOperationException();
    		}
    	  
    		public String getName() {
    				throw new UnsupportedOperationException();
    		}
    		public String getDescription() {
    				throw new UnsupportedOperationException();
    		}
    		public double getPrice() {
    				throw new UnsupportedOperationException();
    		}
    		public boolean isVegetarian() {
    				throw new UnsupportedOperationException();
    		}
    	  
    		public void print() {
    				throw new UnsupportedOperationException();
    		}
    }
    메뉴 컴포지트 추상클래스
    java
    public class MenuItem extends MenuComponent {
    		String name;
    		String description;
    		boolean vegetarian;
    		double price;
    	    
    		public MenuItem(String name, 
    		                String description, 
    		                boolean vegetarian, 
    		                double price) 
    		{ 
    				this.name = name;
    				this.description = description;
    				this.vegetarian = vegetarian;
    				this.price = price;
    		}
    	  
    		public String getName() {
    				return name;
    		}
    	  
    		public String getDescription() {
    				return description;
    		}
    	  
    		public double getPrice() {
    				return price;
    		}
    	  
    		public boolean isVegetarian() {
    				return vegetarian;
    		}
    	  
    		public void print() {
    				System.out.print("  " + getName());
    				if (isVegetarian()) {
    						System.out.print("(v)");
    				}
    				System.out.println(", " + getPrice());
    				System.out.println("     -- " + getDescription());
    		}
    }
    추상 클래스의 구현 클래스 Leaf 노드에 해당함
    java
    public class Menu extends MenuComponent {
    		ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
    		String name;
    		String description;
    	  
    		public Menu(String name, String description) {
    				this.name = name;
    				this.description = description;
    		}
    	 
    		public void add(MenuComponent menuComponent) {
    				menuComponents.add(menuComponent);
    		}
    	 
    		public void remove(MenuComponent menuComponent) {
    				menuComponents.remove(menuComponent);
    		}
    	 
    		public MenuComponent getChild(int i) {
    				return (MenuComponent)menuComponents.get(i);
    		}
    	 
    		public String getName() {
    				return name;
    		}
    	 
    		public String getDescription() {
    				return description;
    		}
    	 
    		public void print() {
    				System.out.print("\n" + getName());
    				System.out.println(", " + getDescription());
    				System.out.println("---------------------");
    				// 재귀적으로 자신의 메뉴 정보를 출력
    			  for (MenuComponent menuComponent : menuComponents) {
    						menuComponent.print();
    				}
    		}
    }
    java
    public class Waitress {
    		MenuComponent allMenus;
    	 
    		public Waitress(MenuComponent allMenus) {
    				this.allMenus = allMenus;
    		}
    	 
    		public void printMenu() {
    				allMenus.print();
    		}
    }
    전체 글 둘러보기