서로 다는 방식으로 저장한 것을 공통으로 다루고 싶다.
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class IteratorTest {
static Supplier<IntStream> supply(){
return ()-> new Random().ints(10, 1, 100);
}
static class ClassArr<E> implements Iterable<E>{
E[] dataArr;
public ClassArr(E[] dataArr) {
this.dataArr = (E[]) dataArr;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int cursor = 0;
public boolean hasNext() {
return cursor < dataArr.length;
}
public E next() {
return dataArr[cursor++];
}
};
}
}
static class MapClass implements Iterable<Map.Entry<Object, List<Integer>>>{
Map<Object, List<Integer>> map = new HashMap<>();
public MapClass() {
map= supply().get().boxed().collect(Collectors.groupingBy(n->n));
}
@Override
public Iterator<Entry<Object, List<Integer>>> iterator() {
return map.entrySet().iterator();
}
}
static class ArrClass implements Iterable<Integer>{
int[] intArr = supply().get().toArray();
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int cursor = 0;
public Integer next() {
return intArr[cursor++];
}
public boolean hasNext() {
return cursor<intArr.length;
}
};
}
}
static class ListClass implements Iterable<Integer>{
List<Integer> intList = supply().get().boxed().toList();
@Override
public Iterator<Integer> iterator() {
return intList.iterator();
}
}
public static void main(String[] args) {
String[] test = {"배열은","향상된","반복문","사용가능"};
//배열 향상 포문 가능
for(String data : test) {
System.out.print(data+" ");
}
System.out.println();
//어떠한 클래스도 Iterable만 알맞게 구현하면 전부 향상 포문 가능하다.
for(String data : new ClassArr<>(test)) {
System.out.print(data+" ");
}
System.out.println();
for(Integer val : new ArrClass()) {
System.out.print(val+" ");
}
System.out.println();
for(Integer val :new ListClass()) {
System.out.print(val+" ");
}
System.out.println();
for(Entry en : new MapClass()) {
System.out.print(en + " ");
}
}
}
배열은 향상된 반복문 사용가능
배열은 향상된 반복문 사용가능
61 13 57 51 30 49 25 5 48 48
34 91 69 72 70 1 18 5 26 55
49=[49] 17=[17] 97=[97] 35=[35] 52=[52] 53=[53] 56=[56] 40=[40] 45=[45] 15=[15]
반복자 패턴 알아보기
반복자 패턴은 Iterator 인터페이스에 의존한다
이 인터페이스만 있으면 배열, 리스트, 해시테이블 등 모든 컬렉션을 순회할 수 있다.
반복자 패턴의 정의
집합체 내에서 어떤 식으로 일이 처리되는지 전혀 모르는 상태에서 그 안에 들어있는 모든 항목을 대상으로 반복 작업을 수행할 수 있다.
또한 서로 다른 종류의 집합체라도 Iterator만 구현해 리턴하면 같은 방법으로 순회를 할 수 있다.
각 집합체는 요소 순회만 Iterator에게 위임하고, 내부 자료구조 관리만 잘하면 된다.
컴포지트 패턴의 정의
반복자 패턴만으론 처리하기 어려워 메뉴 관리에 도움되는 컴포지트 패턴 도임
객체를 트리구조로 구성해서 부분-전체 계층구조를 구현한다. 컴포지트 패턴을 사용하면 클라이언트에서 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있다.
import java.util.ArrayList;
import java.util.List;
public class CompositeTest {
//구성요소
static 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();
}
}
//잎
static 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 boolean isVegetarian() {
return vegetarian;
}
public double getPrice() {
return price;
}
public void print() {
System.out.print(" "+getName());
if(isVegetarian()) {
System.out.print("(v)");
}
System.out.println(", "+getPrice());
System.out.println(" -- "+getDescription());
}
}
//노드
static class Menu extends MenuComponent{
List<MenuComponent> menuComponents = new ArrayList<>();
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 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();
}
}
}
static class Waitress{
MenuComponent allmenus;
public Waitress(MenuComponent allmenus) {
this.allmenus = allmenus;
}
public void printMenu() {
allmenus.print();
}
}
public static void main(String[] args) {
MenuComponent phMenu = new Menu("팬케이크 하우스 메뉴", "아침 메뉴");
MenuComponent dinerMenu = new Menu("객체마을 식당 메뉴", "점심 메뉴");
MenuComponent cafeMenu = new Menu("카페 메뉴", "저녁 메뉴");
MenuComponent dessertMenu = new Menu("디저트 메뉴", "디저트를 즐겨 보에쇼");
MenuComponent allMenu = new Menu("전체 메뉴", "전체 메뉴");
allMenu.add(phMenu);
allMenu.add(dinerMenu);
allMenu.add(cafeMenu);
phMenu.add(
new MenuItem("K&B 팬케이크 아침정식"
,"팬케이크에 스크램블에그와 토스트", true, 2.99));
phMenu.add(
new MenuItem("레귤러 팬케이크 아침정식"
,"팬케이크에 계란 후라이와 소세지", false, 2.99));
phMenu.add(
new MenuItem("블루베리 팬케이크"
,"팬케이크와 블루베리, 블루베리 시럽", true, 3.49));
phMenu.add(
new MenuItem("와플"
,"와플과 블루베리 또는 딸기를 드립니다.", true, 3.59));
dinerMenu.add(
new MenuItem("채식주의자용 BLT"
, "통밀 위에 콩고기 베이컨, 상추, 토마토를 얹은 메뉴", true, 2.99));
dinerMenu.add(
new MenuItem("BLT"
, "통밀 위에 베이컨, 상추, 토마토를 얹은 메뉴", false, 2.99));
dinerMenu.add(
new MenuItem("오늘의 스프"
, "감자 샐러드를 곁들인 오늘의 스프", true, 2.99));
dinerMenu.add(
new MenuItem("핫도그"
, "사워크라우트, 갖은 양념, 양파, 치즈가 곁들여진 핫도그", true, 2.99));
dinerMenu.add(
new MenuItem("파스타"
, "마리나라 소스 스파게티, 효모빵도 드립니다.", true, 3.89));
dinerMenu.add(dessertMenu);
dessertMenu.add(
new MenuItem("애플 파이"
, "바삭바삭한 크러스트에 바닐라 아이스크림이 얹혀 있는 애플 파이", true, 1.59));
dessertMenu.add(
new MenuItem("치즈케이크"
, "초콜릿 그레이엄 크러스트 위에 부드러운 뉴욕 치즈케이크", true, 1.99));
dessertMenu.add(
new MenuItem("소르베"
, "라스베리와 라임의 절묘한 조화", true, 1.89));
cafeMenu.add(
new MenuItem("베지 버거와 에어 프라이"
, "통밀빵, 상추, 토마토, 감자 튀김이 첨가된 베지 버거", true, 1.59));
cafeMenu.add(
new MenuItem("오늘의 스프"
, "통밀빵, 상추, 토마토, 감자 튀김이 첨가된 베지 버거", false, 0.69));
cafeMenu.add(
new MenuItem("투리토"
, "통 핀토콩과 살사, 구아카몰이 곁들여진 푸짐한 부리토", true, 0.89));
Waitress waitress = new Waitress(allMenu);
waitress.printMenu();
}
}
전체 메뉴, 전체 메뉴
----------------------
팬케이크 하우스 메뉴, 아침 메뉴
----------------------
K&B 팬케이크 아침정식(v), 2.99
-- 팬케이크에 스크램블에그와 토스트
레귤러 팬케이크 아침정식, 2.99
-- 팬케이크에 계란 후라이와 소세지
블루베리 팬케이크(v), 3.49
-- 팬케이크와 블루베리, 블루베리 시럽
와플(v), 3.59
-- 와플과 블루베리 또는 딸기를 드립니다.
객체마을 식당 메뉴, 점심 메뉴
----------------------
채식주의자용 BLT(v), 2.99
-- 통밀 위에 콩고기 베이컨, 상추, 토마토를 얹은 메뉴
BLT, 2.99
-- 통밀 위에 베이컨, 상추, 토마토를 얹은 메뉴
오늘의 스프(v), 2.99
-- 감자 샐러드를 곁들인 오늘의 스프
핫도그(v), 2.99
-- 사워크라우트, 갖은 양념, 양파, 치즈가 곁들여진 핫도그
파스타(v), 3.89
-- 마리나라 소스 스파게티, 효모빵도 드립니다.
디저트 메뉴, 디저트를 즐겨 보에쇼
----------------------
애플 파이(v), 1.59
-- 바삭바삭한 크러스트에 바닐라 아이스크림이 얹혀 있는 애플 파이
치즈케이크(v), 1.99
-- 초콜릿 그레이엄 크러스트 위에 부드러운 뉴욕 치즈케이크
소르베(v), 1.89
-- 라스베리와 라임의 절묘한 조화
카페 메뉴, 저녁 메뉴
----------------------
베지 버거와 에어 프라이(v), 1.59
-- 통밀빵, 상추, 토마토, 감자 튀김이 첨가된 베지 버거
오늘의 스프, 0.69
-- 통밀빵, 상추, 토마토, 감자 튀김이 첨가된 베지 버거
투리토(v), 0.89
-- 통 핀토콩과 살사, 구아카몰이 곁들여진 푸짐한 부리토
'IT책, 강의 > 헤드 퍼스트 디자인 패턴' 카테고리의 다른 글
CHAPTER 11 객체 접근 제어하기 프록시 패턴 (0) | 2023.06.03 |
---|---|
CHAPTER 10 객체의 상태 바꾸기 상태 패턴 (0) | 2023.06.01 |
CHAPTER 08 알고리즘 캡슐화하기 템플릿 메소드 패턴 (0) | 2023.05.28 |
CHAPTER 07 적응시키기 어댑터 패턴과 퍼사드 패턴 (0) | 2023.05.26 |
CHAPTER 06 호출 캡슐화하기 커맨드 패턴 (0) | 2023.05.24 |