디자인 모드 chapter 09 - 교체 기 및 조합 모드
머리말
대상 을 쌓 아 집합 (collection) 으로 만 드 는 방법 은 많다.너 는 그들 을 배열, 스 택, 또는 흩 어 진 목록 에 넣 을 수 있다. 이것 은 너의 자유 이다.모든 것 은 자신의 장점 과 적당 한 사용 시기 가 있 지만 한 번 은 고객 이 이런 대상 을 옮 겨 다 니 고 싶 을 때 가 있 습 니 다. 그 가 이렇게 할 때 고객 에 게 당신 의 실현 을 보 여 주 려 고 합 니까?우 리 는 당연히 안 했 으 면 좋 겠 지!이 건 너무 프로 답지 못 하 다.괜 찮 습 니 다. 당신 의 일 에 대해 걱정 하지 마 세 요. 당신 은 이 장 에서 고객 이 당신 의 대상 을 옮 겨 다 니 며 저장 대상 을 엿 볼 수 없 는 방법 을 배 울 것 입 니 다.일부 대상 집합 (슈퍼 collection) 을 만 드 는 방법 도 배 워 서 보기 만 해도 무 서운 데이터 구 조 를 단숨에 뛰 어 넘 을 수 있 습 니 다.너 는 대상 의 직책 에 관 한 지식 도 배 울 것 이다.
본문
2.1 대상 마을 식당 과 대상 마을 전병 집 이 합병 되 었 다
이것 은 정말 좋 은 소식 이다. 이제 우 리 는 같은 곳 에서 두 가지 식품 을 사용 할 수 있 게 되 었 다.그런데 좀 귀 찮 은 것 같 아 요.부침 개 집 메뉴 는 배열 로 저장 되 고 식당 메뉴 는 Array List 로 저장 된다.적어도 두 식당 모두 아래 코드 에 따라 메뉴 항목 (단독 메뉴) 을 통일 한다.
메뉴 항목 구현:
public class MenuItem {
String name;
String description;
boolean vegetarian;
double price;
/*
* 、 、 、
*
*
* getter
*/
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 class PancakeHouseMenu implements Menu {
ArrayList menuItems;
/*
*
* ArrayList
* , ArrayList
*
* , : , ,
* ArrayList
*/
public PancakeHouseMenu() {
menuItems = new ArrayList();
addItem("K&B's Pancake Breakfast",
"Pancakes with scrambled eggs, and toast",
true,
2.99);
addItem("Regular Pancake Breakfast",
"Pancakes with fried eggs, sausage",
false,
2.99);
addItem("Blueberry Pancakes",
"Pancakes made with fresh blueberries",
true,
3.49);
addItem("Waffles",
"Waffles, with your choice of blueberries or strawberries",
true,
3.59);
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public ArrayList getMenuItems() {
return menuItems;
}
}
식당 메뉴 구현
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
/*
* 1 , , ,
* 2 , addItem()
* 3 addItem() , 。
*
*/
public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT",
"(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
addItem("BLT",
"Bacon with lettuce & tomato on whole wheat", false, 2.99);
addItem("Soup of the day",
"Soup of the day, with a side of potato salad", false, 3.29);
addItem("Hotdog",
"A hot dog, with saurkraut, relish, onions, topped with cheese",
false, 3.05);
addItem("Steamed Veggies and Brown Rice",
"Steamed vegetables over brown rice", true, 3.99);
addItem("Pasta",
"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
true, 3.89);
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.err.println("Sorry, menu is full! Can't add item to menu");
} else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
}
이상 실현 의 단점:
1. 우 리 는 Pancake House Menu 와 Dinner Menu 의 구체 적 인 실현 코드 를 대상 으로 하 는 것 이지 인 터 페 이 스 를 대상 으로 하 는 것 이 아 닙 니 다.
2. 만약 에 우리 가 Dinner Menu 에서 다른 메뉴 로 전환 하기 로 결정 하면 이 메뉴 의 항목 은 Hash Table 로 저장 되 기 때문에 우 리 는 여급 중의 많은 코드 를 수정 해 야 합 니 다.
3. 여자 접 대 는 각 메뉴 가 내부 의 메뉴 항목 집합 을 어떻게 표현 하 는 지 알 아야 한다. 이것 은 포장 위반 이다.
4. 우 리 는 중복 되 는 코드 가 있 습 니 다. printMenu () 방법 은 두 가지 서로 다른 메뉴 를 옮 겨 다 니 는 두 가지 순환 이 필요 합 니 다.만약 우리 가 세 번 째 메뉴 를 더 한다 면, 우 리 는 세 가지 순환 이 필요 하 다.
2.2 회견 교체 기 모드
교체 기 모드 에 대해 알 아야 할 첫 번 째 일 은 교체 기 라 는 인터페이스 에 의존 하 는 것 이다.
하나의 교체 기 는 두 개의 인 터 페 이 스 를 포함 합 니 다. hasNext () 방법 은 이 집합 에 더 많은 요소 가 있 는 지 알려 줍 니 다. next () 방법 은 이 집합 중의 다음 대상 을 되 돌려 줍 니 다.
지금 우 리 는 식당 메뉴 를 위해 구체 적 인 교체 기 를 실현 해 야 한다.
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;
/*
*
* 1 position
* 2
* 3 next() ,
* 4 hasNext() 。 , true
* 5 , null
*/
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
public Object 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;
}
}
}
여급 코드
public class Waitress {
Menu pancakeHouseMenu;
Menu dinerMenu;
public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();
System.out.println("MENU
----
BREAKFAST");
printMenu(pancakeIterator);
System.out.println("
LUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
System.out.print(menuItem.getName() + ", ");
System.out.print(menuItem.getPrice() + " -- ");
System.out.println(menuItem.getDescription());
}
}
}
모든 것 을 정리 하기 전에 현재 의 디자인 을 전체적으로 살 펴 보 자.
1. 두 메뉴 가 같은 인 터 페 이 스 를 실현 합 니 다.
2. 부침 개 집 메뉴 와 식당 메뉴 는 모두 새로운 create Iterator () 방법 을 실 현 했 고 각자 의 메뉴 항목 에 교체 기 를 만 드 는 것 을 책임 집 니 다.
3. 교체 기 는 여급 이 구체 적 인 유형의 실현 에서 결합 을 풀 수 있 도록 한다.그녀 는 메뉴 가 배열, Array List 를 사용 하 는 지, 아니면 포스트 잇 을 사용 하 는 지 알 필요 가 없다.그녀 는 그녀 가 얻 을 수 있 는 교체 기 에 만 관심 이 있다.
2.3 교체 기 모드 정의
교체 기 모드: 집합 대상 의 각 요 소 를 방문 하고 내부 의 표 시 를 드 러 내지 않 는 방법 을 제공 합 니 다.
이것 은 매우 의미 가 있다. 이 모델 은 집합 대상 의 요 소 를 순서대로 방문 할 수 있 고 내부 가 어떻게 표시 되 는 지 모른다.
다른 팀 은 당신 의 디자인 에 중요 한 영향 을 미 쳤 습 니 다. 교체 기 모델 은 요소 사 이 를 돌아 다 니 는 책임 을 집적 대상 이 아니 라 교체 기 에 게 맡 깁 니 다.이 는 취 합 된 인터페이스 와 실현 을 더욱 간결 하 게 만 들 뿐만 아니 라 취 합 이 집중 해 야 할 일 에 도 집중 할 수 있다.
단일 책임: 한 가지 유형 은 변 화 를 일 으 키 는 원인 만 있어 야 한다.
클래스 의 모든 책임 은 변 하 는 잠재 적 인 구역 이 있다.하나의 책임 을 초과 하 는 것 은 변 화 된 지역 을 초과 하 는 것 을 의미한다.
이 원칙 은 우리 에 게 가능 한 한 모든 유형 이 단일 책임 을 유지 하도록 하 는 것 을 알려 준다.
어떻게 해결 할 까요?이것 은 듣 기 에는 매우 쉽 지만 사실은 하기 가 결코 간단 하지 않다. 디자인 의 책임 을 구분 하 는 것 이 가장 어 려 운 일 중의 하나 이다.우리 의 뇌 는 한 무리의 행동 을 보고 그들 을 한데 모 으 는 것 에 익숙 하 다.우리 의 뇌 는 한 무리의 행동 을 보고 그것 을 한데 모 으 는 것 에 익숙 하 다. 비록 그들 이 두 개 혹은 여러 개의 다른 책임 에 속 할 수 있 지만.
성공 하고 자 하 는 유일한 방법 은 당신 의 디자인 을 꾸준히 검사 하 는 것 입 니 다. 시스템 이 성장 함 에 따라 어떤 변화 가 나타 나 는 원인 이 하나 이상 인지 수시로 관찰 하 는 것 입 니 다.
2.4 교체 기와 집합
우리 가 사용 하 는 이 클래스 들 은 모두 자바 Collection Framework 의 일부분 에 속한다.여기 서 프레임 워 크 란 Array List, Vector, LinkedList, Stack 과 Priority Queue 를 포함 한 클래스 와 인 터 페 이 스 를 말한다.이 클래스 들 은 모두 자바 util. collection 인 터 페 이 스 를 실현 했다.이 인 터 페 이 스 는 많은 유용 한 방법 을 포함 하고 있어 서 한 무리의 대상 을 조종 할 수 있다.
자바 5 의 교체 기와 집합
자바 5 는 새로운 형세 의 for 문 구 를 포함 하여 for / in 이 되 었 다.이것 은 집합 이나 배열 을 옮 겨 다 닐 수 있 으 며, 명시 적 으로 교체 기 를 만 들 필요 가 없다.for / in 을 사용 하고 싶 습 니 다. 문법 은 이 렇 습 니 다.
for (Object obj: collection)
{
/ / 동작
}
2.5 초기 조합 모드
우리 가 이 모든 것 이 완벽 하 다 고 생각 할 때, 지금 그들 은 할 수 있 기 를 바란다.
디저트 를 곁 들 인 하위 메뉴.
만약 우리 가 디저트 메뉴 를 식당 메뉴 의 집합 요 소 를 프로 그래 밍 할 수 있다 면 얼마나 좋 을 까.하지만 지금의 실현 에 따라 근 거 는 할 수 없다.
그래서 우리 의 새로운 디자인 에서 정말 무엇이 필요 합 니까?
1 메뉴, 하위 메뉴, 메뉴 항목 을 수용 할 수 있 는 트 리 구조 가 필요 합 니 다.
2. 우 리 는 모든 메뉴 의 각 항목 사 이 를 돌아 다 닐 수 있 는 지 확인 해 야 한다. 그리고 적어도 지금 교체 기 를 사용 하 는 것 처럼 편리 해 야 한다.
3. 우리 도 메뉴 항목 사 이 를 좀 더 탄력 있 게 돌아 다 닐 수 있어 야 한다.예 를 들 어 디저트 메뉴 만 옮 겨 다 니 거나 식당 의 전체 메뉴 (디저트 메뉴 포함) 를 옮 겨 다 닐 수 있 습 니 다.
조합 모드: 대상 을 트 리 구조 로 조합 하여 '전체 / 부분' 차원 구 조 를 표현 할 수 있 도록 합 니 다.조합 은 고객 으로 하여 금 일치 하 는 방식 으로 개별 대상 과 대상 조합 을 처리 하 게 할 수 있다.
조합 모드 는 트 리 방식 으로 대상 의 구 조 를 만 들 수 있 고 트 리 에는 조합 과 개별 대상 이 포함 되 어 있 습 니 다.
조합 기 구 를 사용 하면 우 리 는 같은 조작 을 조합 과 개별 대상 에 응용 할 수 있다.대부분의 경우 대상 조합 과 개별 대상 간 의 차 이 를 무시 할 수 있다 는 얘 기다.
2.6 조합 디자인 메뉴 활용
우 리 는 어떻게 메뉴 에 조합 모드 를 적용 해 야 합 니까?처음에는 메뉴 와 메뉴 항목 의 공동 인터페이스 로 구성 요소 인 터 페 이 스 를 만들어 서 메뉴 와 메뉴 항목 을 통일 적 으로 처리 할 수 있 도록 해 야 합 니 다.메뉴 나 메뉴 항목 에 대해 같은 방법 을 사용 할 수 있다 는 얘 기다.
메뉴 구성 요 소 를 실현 하려 면 모든 구성 요소 가 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();
}
}
메뉴 항목 구현
public class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;
/*
* 1 MenuComponent
* 2 , toString()
*/
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());
}
}
조합 메뉴 구현
public class Menu extends MenuComponent {
ArrayList menuComponents = new ArrayList();
String name;
String description;
/*
* 1 , MenuComponent
* 2 , MenuComponent , ArrayList
* 3 。 MenuComponent,
* 4 , MenuComponent
*/
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("
" + getName());
System.out.println(", " + getDescription());
System.out.println("---------------------");
Iterator iterator = menuComponents.iterator();
while (iterator.hasNext()) {
MenuComponent menuComponent =
(MenuComponent)iterator.next();
menuComponent.print();
}
}
}
테스트 프로그램 작성
public class MenuTestDrive {
public static void main(String args[]) {
/*
* 1
* 2 , allMenus
* 3 add() , allMenu()
* 4
* 5
* 6 , , , ,
*/
MenuComponent pancakeHouseMenu =
new Menu("PANCAKE HOUSE MENU", "Breakfast");
MenuComponent dinerMenu =
new Menu("DINER MENU", "Lunch");
MenuComponent cafeMenu =
new Menu("CAFE MENU", "Dinner");
MenuComponent dessertMenu =
new Menu("DESSERT MENU", "Dessert of course!");
MenuComponent coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee");
MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
allMenus.add(pancakeHouseMenu);
allMenus.add(dinerMenu);
allMenus.add(cafeMenu);
pancakeHouseMenu.add(new MenuItem(
"K&B's Pancake Breakfast",
"Pancakes with scrambled eggs, and toast",
true,
2.99));
pancakeHouseMenu.add(new MenuItem(
"Regular Pancake Breakfast",
"Pancakes with fried eggs, sausage",
false,
2.99));
pancakeHouseMenu.add(new MenuItem(
"Blueberry Pancakes",
"Pancakes made with fresh blueberries, and blueberry syrup",
true,
3.49));
pancakeHouseMenu.add(new MenuItem(
"Waffles",
"Waffles, with your choice of blueberries or strawberries",
true,
3.59));
dinerMenu.add(new MenuItem(
"Vegetarian BLT",
"(Fakin') Bacon with lettuce & tomato on whole wheat",
true,
2.99));
dinerMenu.add(new MenuItem(
"BLT",
"Bacon with lettuce & tomato on whole wheat",
false,
2.99));
dinerMenu.add(new MenuItem(
"Soup of the day",
"A bowl of the soup of the day, with a side of potato salad",
false,
3.29));
dinerMenu.add(new MenuItem(
"Hotdog",
"A hot dog, with saurkraut, relish, onions, topped with cheese",
false,
3.05));
dinerMenu.add(new MenuItem(
"Steamed Veggies and Brown Rice",
"Steamed vegetables over brown rice",
true,
3.99));
dinerMenu.add(new MenuItem(
"Pasta",
"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
true,
3.89));
dinerMenu.add(dessertMenu);
dessertMenu.add(new MenuItem(
"Apple Pie",
"Apple pie with a flakey crust, topped with vanilla icecream",
true,
1.59));
dessertMenu.add(new MenuItem(
"Cheesecake",
"Creamy New York cheesecake, with a chocolate graham crust",
true,
1.99));
dessertMenu.add(new MenuItem(
"Sorbet",
"A scoop of raspberry and a scoop of lime",
true,
1.89));
cafeMenu.add(new MenuItem(
"Veggie Burger and Air Fries",
"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
true,
3.99));
cafeMenu.add(new MenuItem(
"Soup of the day",
"A cup of the soup of the day, with a side salad",
false,
3.69));
cafeMenu.add(new MenuItem(
"Burrito",
"A large burrito, with whole pinto beans, salsa, guacamole",
true,
4.29));
cafeMenu.add(coffeeMenu);
coffeeMenu.add(new MenuItem(
"Coffee Cake",
"Crumbly cake topped with cinnamon and walnuts",
true,
1.59));
coffeeMenu.add(new MenuItem(
"Bagel",
"Flavors include sesame, poppyseed, cinnamon raisin, pumpkin",
false,
0.69));
coffeeMenu.add(new MenuItem(
"Biscotti",
"Three almond or hazelnut biscotti cookies",
true,
0.89));
Waitress waitress = new Waitress(allMenus);
waitress.printMenu();
}
}
조합 모델 에 대한 작은 의문.
조합 모드 는 단일 책임 설계 원칙 으로 투명 성 (transparency) 을 얻는다.투명 성 이란 무엇 인가?구성 요소 와 인 터 페 이 스 를 관리 하 는 서브 노드 와 잎 노드 의 조작 을 동시에 포함 시 키 면 고객 은 조합 과 잎 노드 를 동일시 할 수 있다.즉, 하나의 요소 가 조합 인지 잎 노드 인지 고객 에 게 투명 하 다 는 것 이다.
그래서 위의 문제 로 돌아 가 는 것 은 전형 적 인 절충 사례 이다.비록 우 리 는 디자인 원칙 에 대해 알 고 있 지만, 우 리 는 항상 어떤 원칙 이 우리 디자인 에 미 치 는 영향 을 관찰 해 야 한다.때때로 우 리 는 고의로 원칙 에 어 긋 나 는 것 처럼 보 이 는 일 을 한다.
2.7 조합 교체 기
1. 우 리 는 Menu Component 에 create Iterator () 방법 을 추가 합 니 다. 이것 은 모든 메뉴 와 메뉴 항목 이 이 방법 을 실현 해 야 한 다 는 것 을 의미 합 니 다. 또한 하나의 조합 에 대해 Create Iterator () 방법 을 호출 하면 이 그룹의 모든 아이들 에 게 적 용 될 것 입 니 다.
2. 지금 우 리 는 메뉴 와 메뉴 항목 에서 이 방법 을 실현 해 야 한다.
이 Composite Iterator 는 무시 할 수 없 는 교체 기 이다.작업실 은 구성 요소 안의 메뉴 항목 을 옮 겨 다 니 며 모든 하위 메뉴 가 포함 되 어 있 는 지 확인 합 니 다.
주의: 여기 서 사용 하 는 재 귀 는 나 에 게 "재 귀 는 나의 친구 이 고 재 귀 는 나의 친구 이다..." 라 고 묵념 했다.
public class CompositeIterator implements Iterator {
Stack stack = new Stack();
public CompositeIterator(Iterator iterator) {
stack.push(iterator);
}
/*
* (non-Javadoc)
* @see java.util.Iterator#next()
* 1 , hasNext()
* 2 , ,
* 3 , , 。 , 。
*/
public Object next() {
if (hasNext()) {
Iterator iterator = (Iterator) stack.peek();
MenuComponent component = (MenuComponent) iterator.next();
if (component instanceof Menu) {
stack.push(component.createIterator());
}
return component;
} else {
return null;
}
}
/*
* (non-Javadoc)
* @see java.util.Iterator#hasNext()
* 1 , ; ,
* 2 , , , , , hasNext()
* 3 , , true
*/
public boolean hasNext() {
if (stack.empty()) {
return false;
} else {
Iterator iterator = (Iterator) stack.peek();
if (!iterator.hasNext()) {
stack.pop();
return hasNext();
} else {
return true;
}
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
3 장 소결
아주 긴 장, 코드 필름 도 적지 않 았 는데, 다행히 마침내 끝 이 났 다.학습 과정 에서 우 리 는 이런 상대 적 으로 긴 학습 주 기 를 자주 만 날 수 있다. 이 럴 때 여러 단계 로 나 누 어 완성 할 수 있 고 자신의 진 도 를 실시 간 으로 기록 할 수 있다. 간단 한 미 완성 / 이미 완성 이 아니 라 일정한 격려 역할 을 할 수 있다.
이 디자인 모델 로 돌아 가면 교체 기 는 낯 설 지 않 을 것 입 니 다. 여기 서 교체 기 인 터 페 이 스 를 사용자 정의 한 것 은 바로 교체 기의 작업 원 리 를 알 게 해 주 는 것 입 니 다.조합 모드 는 재 귀 알고리즘 과 결합 하여 트 리 구 조 를 처리 할 때 절대 이기 입 니 다.이전에 작은 도 구 를 쓸 때 도 비슷 한 문제 에 부 딪 힌 적 이 있다. 그 때 는 이런 이기 가 있 는 지 몰 랐 고 자신의 생각 으로 기능 을 실현 했다. 최적화 가능성 이 있 는 지 돌 이 켜 보 았 다.수 요 는 간단 합 니 다. Excel 의 기록 을 트 리 구조 에 따라 xml 파일 로 출력 합 니 다. 관심 이 있 는 학생 들 은 제 이전 블 로 그 를 볼 수 있 습 니 다 (http://blog.csdn.net/adoaiwen1314/article/details/17075491) 조합 교체 기 모드 로 디자인 된 코드 를 제시 한 것 을 환영 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
디자인 모델 의 공장 모델, 단일 모델자바 는 23 가지 디자인 모델 (프로 그래 밍 사상/프로 그래 밍 방식) 이 있 습 니 다. 공장 모드 하나의 공장 류 를 만들어 같은 인 터 페 이 스 를 실현 한 일부 종 류 를 인 스 턴 스 로 만 드 는 것...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.