public class DinerMenu {
static final int MAX_ITMES = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITMES];
addItem("채식주의자용 BLT", "통밀 위에 콩고기 베이컨, 상추, 토마토 얹은 메뉴", true, 2.99);
addItem("BLT", "BLT", false, 2.99);
addItem("핫도그", "핫도그", false, 3.29);
addItem("스프", "스프", false, 3.05);
}
private void addItem(String name, String description, boolean vegetarain, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarain, price);
if(numberOfItems >= MAX_ITMES) {
System.out.println("죄송합니다, 메뉴가 꽉 찼습니다. 더이상 추가 할 수 없습니다.");
}else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems +1;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
}
import java.util.ArrayList;
import java.util.List;
class PancakeHouseMenu {
List<MenuItem> menuItems;
public PancakeHouseMenu() {
menuItems = new ArrayList<MenuItem>();
addItem("펜케이크 세트","스크램블",true, 2.99);
addItem("레귤러 펜케이크 세트","소시지",false, 2.99);
addItem("블루베리 펜케이크 세트","블루베리",true, 3.49);
addItem("와플","와플",true, 3.59);
}
private void addItem(String name, String description, boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price)
menuItems.add(menuItem);
}
public List<MenuItem> getMenuItems() {
return menuItems;
}
}
다음과 같이 두 메뉴 구현 방식이 틀린 코드를 합치고 싶을 때
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
ArrayList<MenuItem> breakfastItems = pancakeHouseMenu.getMenuItems();
DinerMenu dinerMenu = new DinerMenu();
MenuItem[] lunchItems = dinerMenu.getMenuItems();
for(int i=0 < breakfastItems.size(); i++) {
....
}
for(int i=0; i<lunchItems.length; i++){
...
}
항상 두 메뉴를 사용하고 각 항목에 반복 작업을 수행하려면 2개의 순한문을 사용해야한다. 다른 레스토랑과 또 합병한다면 3개 순한문이 필요해지는 문제가 발생한다.
Iterator iterator = breakfastMenu.createIterator();
while(iterator.hasNext()){
MenuItem menuIte = iterator.next();
}
Iterator iterator = lunchMenu.createIterator();
while(iterator.hasNext()){
MenuItem menuItem = iterator.next();
}
public interface Iterator{
boolean hasNext();
MenuItem next();
}
public class DinerMenu implements Menu {
static final int MAX_ITMES = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITMES];
addItem("채식주의자용 BLT", "통밀 위에 콩고기 베이컨, 상추, 토마토 얹은 메뉴", true, 2.99);
addItem("BLT", "BLT", false, 2.99);
addItem("핫도그", "핫도그", false, 3.29);
addItem("스프", "스프", false, 3.05);
}
private void addItem(String name, String description, boolean vegetarain, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarain, price);
if(numberOfItems >= MAX_ITMES) {
System.out.println("죄송합니다, 메뉴가 꽉 찼습니다. 더이상 추가 할 수 없습니다.");
}else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems +1;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
}
전용 Iterator 적용
public class DinerMenuIterator implements Iterator{
MenuItem[] items;
int position = 0;
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(position >= items.length || items[position] == null) {
return false;
}else {
return true;
}
}
@Override
public MenuItem next() {
// TODO Auto-generated method stub
MenuItem menuItem = items[position];
position = position +1;
return menuItem;
}
}
종업원
public class Waitress {
Menu pancakeHouseMenu;
Menu dinerMenu;
public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();
System.out.println("메뉴");
printMenu(pancakeIterator);
System.out.println("다음");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator) {
while(iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
System.out.println(menuItem.getName());
System.out.println(menuItem.getPrice());
System.out.println(menuItem.getDescription());
}
}
}
테스트시

반복자 패턴은 컬렉션 구현방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공
어떤 클래스가 바뀌는 이유는 하나뿐이어야한다
for(MenuItem item: menu) {
}
public class CafeMenu implements Menu{
Map<String, MenuItem> menuItems = new HashMap();
public CafeMenu() {
addItem("버거", "설명", true, 3.39);
}
public void addItem(String name, String description, boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.put(name, menuItem);
}
@Override
public Iterator<MenuItem> createIterator() {
// TODO Auto-generated method stub
return menuItems.values().iterator();
}
}
컴포지트 패턴으로 객체를 트리구조로 구성해서 부분 - 전체 계층 구조를 구현 컴포지트 패턴 사용하면 클라이언트에서 개별 객체와 복합 객체를 같은 방식으로 다룰 수 있습니다.
menuComponent
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();
}
}
menu
public class Menu extends MenuComponent{
List<MenuComponent> menuComponents = new ArrayList();
String name;
String description;
public Menu(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
@Override
public void add(MenuComponent menuComponent) {
// TODO Auto-generated method stub
menuComponents.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
// TODO Auto-generated method stub
menuComponents.remove(menuComponent);
}
@Override
public MenuComponent getChild(int i) {
// TODO Auto-generated method stub
return menuComponents.get(i);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return description;
}
@Override
public void print() {
System.out.println(getName());
System.out.println(getDescription());
for(MenuComponent menuComponent: menuComponents) {
menuComponent.print();
}
}
}
menuItem
class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name, String description, boolean vegetarian, double price) {
super();
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isVegetarian() {
return this.vegetarian;
}
public double getPrice() {
return price;
}
public void print() {
System.out.println(getName());
if(isVegetarian()) {
System.out.println("v");
}
System.out.println(getPrice());
System.out.println(getDescription());
}
}
종업원
public class Waitress {
MenuComponent menuComponent;
public Waitress(MenuComponent allMenus) {
this.menuComponent = allMenus;
}
public void printMenu() {
menuComponent.print();
}
}
테스트
public class MenuTestDrive {
public static void main(String[] args) {
MenuComponent pankaeHouseMenu = new Menu("케잌", "아침");
MenuComponent dessertMenu = new Menu("디저트", "디저트");
MenuComponent allMenu = new Menu("전체", "전체");
allMenu.add(pankaeHouseMenu);
dessertMenu.add(new MenuItem("애플파이", "바삭", true, 3.5));
allMenu.add(dessertMenu);
Waitress waitress = new Waitress(allMenu);
waitress.printMenu();
}
}