해당 포스팅은 한빛 미디어 헤드퍼스트 디자인 패턴(에릭 프리먼, 엘리자베스 롭슨 저)를 통해 공부한 내용을 정리한 블로그입니다.

아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
좋은 프로그래머는 자기 두뇌를 사용한다. 그러나 좋은 가이드라인은 모든 케이스를 고려해야만 하는 노력을 줄여준다.
(Francis Glassborow, 개발자)

문제점


각자 다른 자료구조 및 구현 방법이 달라 코드를 통일시킬 수가 없음.

PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); 
ArrayList<MenuItem> breakfastItems = pancakeHouseMenu.getMenuItems();

DinerMenu dinerMenu = new DinerMenu(); 
MenuItem[] lunchItems = dinerMenu.getMenuItems();

for (int i = 0; i < breakfastItems.size(); i++) { 
	MenuItem menuItem = breakfastItems.get(i); 
	System.out.print(menuItem.getName() + " "); 
	System.out.println(menuItem.getPrice() + " "); 
	System.out.println(menuItem.getDescription());
}

for (int i = 0; i < lunchItems.length; i++) {
	MenuItem menuItem = lunchItems[i];
    System.out.print(menuItem.getName() + " ");
    System.out.println(menuItem.getPrice() + " ");
    System.out.println(menuItem.getDescription());
}
  • PancakeHouse는 메뉴를 List로 관리.
  • Diner는 메뉴를 array로 관리

반복을 캡슐화하기


디자인 패턴의 기본: 바뀌는 부분을 캡슐화하라!

class diagram

Iterator iterator = breakfastMenu.createIterator();
while (iterator.hasNext()) {
	MenuItem menuItem = iterator.next();
}

Iterator iterator = lunchMenu.createIterator();
while (iterator.hasNext()) {
	MenuItem menuItem = iterator.next();
}

public class PancakeHouseMenuIterator implements Iterator {
	List<MenuItem> items;
	int position = 0;
 
	public PancakeHouseMenuIterator(List<MenuItem> items) {
		this.items = items;
	}
 
	public MenuItem next() {
		return items.get(position++);
	}
 
	public boolean hasNext() {
		return items.size() > position;
	}
}


public class DinerMenuIterator implements Iterator {
	MenuItem[] items;
	int position = 0;
 
	public DinerMenuIterator(MenuItem[] items) {
		this.items = items;
	}
 
	public MenuItem next() {
		return items[position++];
	}
 
	public boolean hasNext() {
		return items.length > position;
    }
}

Iterator Pattern

Iterator Pattern

  • 반복 작업을 캡슐화
  • Iteraotr 인터페이스의 메소드. hasNext(), next()
  • 메뉴 구현이 캡슐화되어 있음
    • 종업원은 메뉴에서 컬렉션을 어떻게 저장하고 있는지 알 필요가 없음.
    • 반복자만 구현한다면 다형성을 활용하여 하나의 반복문으로 처리 가능.
    • 종업원은 인터페이스만 알면 됨.
💡 Iterator Pattern
컬렉션의 구현방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법 제공.
  • 인터페이스와 구현이 간단.
  • 각자의 비즈니스 로직만 처리 가능
  • 확장 가능성이 좋음

구조

  • 공통된 인터페이스를 클라이언트가 참조할 수 있도록 개발.
  • 서브 클래스는 인터페이스에 따라 개발.

단일 역할 원칙

  • 어떤 클래스가 바뀌는 이유는 하나뿐 이여야 한다.

Iterable 인터페이스

  • 어떤 클래스던 Iterable을 구현한다면 그 클래스는 iterator() 메소드를 구현
    • Iterator 인터페이스를 구현하는 반복자 리턴
  • forEach() 메소드 제공

새로운 문제점


public void printMenu() {
	Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator();
    Iterator<MenuItem> dinerIterator = dinerMenu.createIterator();
    Iterator<MenuItem> cafeIterator = cafeMenu.createIterator();
    
    System.out.println("메뉴\n----\n아침 메뉴"); printMenu(pancakeIterator);
    System.out.println("\n점심 메뉴"); printMenu(dinerIterator);
    System.out.println("\n저녁 메뉴");
    
    printMenu(cafeIterator);
}
  • 메뉴들이 추가가 되면 OCP(Open-Closed Principle)에 위배됨.
  • 메뉴를 한꺼번에 관리할 방법이 필요함.
public class Waitress {
    List<Menu> menus;
    
    public Waitress(List<Menu> menus) {
    	this.menus = menus;
    }
    
    public void printMenu() {
    	Iterator<Menu> menuIterator = menus.iterator();
        while(menuIterator.hasNext()) {
        	Menu menu = menuIterator.next();
            printMenu(menu.createIterator()); 
        }
    }
    
	void printMenu(Iterator<MenuItem> iterator) { 
    	while (iterator.hasNext()) {
			MenuItem menuItem = iterator.next();
            
            System.out.print(menuItem.getName() + ", ");
            System.out.print(menuItem.getPrice() + " -- ");
            System.out.println(menuItem.getDescription());
		} 		
	}
}

Composite Pattern


💡 컴포지트 패턴
객체를 트리구조로 구성해서 부분-전체 계층 구조를 구현. 컴포지트 패턴을 사용하면 클라이언트에서 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있음.
  • 단일 역할 원칙을 깨는 대신 투명성을 확보하는 패턴
    • Component 인터페이스에 자식들을 관리하는 기능과 잎으로써의 기능을 전부 넣어서 클라이언트가 복합 객체와 잎을 똑같은 방식으로 처리할 수 있도록 만들었음.
  • 상황에 따라 원칙을 적절하게 사용해야 함.

'기타 > 디자인패턴' 카테고리의 다른 글

[Design Pattern] Proxy Pattern  (2) 2024.06.10
[Design Pattern] State Pattern  (0) 2024.06.09
[Design Pattern] Template Method Pattern  (0) 2024.06.05
[Design Pattern] Adapter Pattern  (0) 2024.06.04
[Design Pattern] Command Pattern  (2) 2024.06.03

+ Recent posts