## 34. 리팩토링: Factory Method 패턴(GoF), Information Expert 패턴(GRASP)
- CSV 데이터 생성을 Board 클래스에 맡기기
- Information Expert 패턴 적용
- CSV 데이터를 가지고 Board 클래스 생성하기
- Factory Method 패턴 적용
- Reflection API 사용법
- Class, Method 사용법
리팩토링: Factory Method 패턴(GoF), Information Expert 패턴(GRASP)
CSV 데이터 생성을 Board 클래스에 맡기기
Information Expert 패턴 적용
Board.java
ㄴ toCsvStirng() 메서드 생성
=> String.format 이용
ㄴ App.java 에서 복사해온 코드 이용
Board.java
ㄴ board -> this 로 변경해줌
App.java
ㄴ toCsvString 으로 메서드 분리
=> Member, Item 도 동일하게 적용
그런데, 여기서 메서드 이름을 toCsvString 이 아닌 toCsv 라고 한다면 통일성이 깨질 것임
Member.java
=> 인터페이스를 이용하자
CsvObject.java
ㄴ bitcamp.vo 패키지에 CsvObject 라는 이름으로 Interface 생성
Board.java
ㄴ 자바에서 다중 상속은 안 되지만 인터페이스는 여러 개 적용할 수 있음 (다중 구현 가능)
Board.java
ㄴ @Override 애노테이션 입력 시 오류 없음
Member.java
ㄴ 자바에서 다중 상속은 안 되지만 인터페이스는 여러 개 적용할 수 있음 (다중 구현 가능)
Member.java
=>
Member.java
ㄴ @Override 애노테이션 입력 시 오류 발생
=> 인터페이스 구조에 맞게 메서드 이름을 변경해줘야 함 -> toCsvString()
App.java
ㄴ toCsv -> toCsvString 로 변경
=> Item 도 동일하게 적용해주기
CSV 데이터를 가지고 Board 클래스 생성하기
- Factory Method 패턴 적용
- Reflection API 사용법
- Class, Method 사용법
App.java
=>
App.java
ㄴ SaveMember -> saveCsv 로 변경
ㄴ Member 대신 CsvObject 로 받음
App.java
ㄴ saveCsv 메서드 이용하도록 코드 변경
App.java
ㄴ 와일드카드(?)를 사용하여 리스트에 어떤 타입의 객체든 저장할 수 있도록 지정한 List 객체를 파라미터로 받도록 코드 변경
ㄴ 리스트 객체를 Object 타입의 객체로 받도록 코드 변경
ㄴ Object 타입으로 받은 obj 레퍼런스 변수가 CsvObject 타입이라는 것을 확실히 알려주기 위해 표시해주기
App.java
ㄴ CsvObject 인터페이스를 구현하고 있는 List 객체만 받아올 수 있도록 구현
=> list 도 CsvObject 타입으로 받아오면 되고, 형변환을 할 필요가 없음
Member.java
ㄴ App 클래스에서 LoadMember() 메서드에서 코드 잘라내와서 이용
App.java
=>
App.java
ㄴ fromCsv() 메서드가 static 으로 선언되어있으므로 Member 클래스 이름을 통해 접근 가능
=> Board 와 Item 클래스도 동일하게 적용하기
App.java
ㄴ Class, Method 사용
ㄴ clazz 매개변수는 CsvObject의 하위 클래스를 나타내는 Class 객체임
ㄴ 여기서 getDeclaredMethod 메서드는 clazz에서 지정된 이름과 매개변수 유형을 가진 메서드를 반환함
ㄴ "fromCsv"는 CsvObject의 하위 클래스에서 정의된 정적 팩토리 메서드의 이름임
ㄴ String.class는 fromCsv 메서드의 매개변수 유형인 String을 나타냄
=> factoryMethod 는 clazz에서 정의된 fromCsv 메서드를 참조하는 Method 객체임
ㄴ 이렇게 얻은 factoryMethod를 사용하여 CSV 데이터를 해당 클래스의 객체로 변환하여 list에 추가할 수 있음
App.java
ㄴ factoryMethod.invoke(null, line)은 factoryMethod를 호출
ㄴ 첫 번째 매개변수 null은 static 메서드를 호출하기 때문에 인스턴스가 필요하지 않음을 나타냄
ㄴ 두 번째 매개변수 line은 fromCsv 메서드의 매개변수인 CSV 데이터를 전달함
App.java
ㄴ <T>는 타입 매개변수를 나타내며, 메서드 호출시 실제 타입으로 대체됨
ㄴ list 매개변수는 List<T>로, T로 지정된 어떤 타입의 객체든 저장할 수 있음을 나타냄
ㄴ clazz 매개변수는 Class<T> 객체로, 로드할 객체의 클래스를 나타냄
App.java
ㄴ 제네릭 타입 매개변수 T를 사용하여 CsvObject의 서브클래스만을 대상으로 로딩하도록 지정
App.java
ㄴ factoryMethod.invoke(null, line) 의 반환타입이 <T> 타입임을 확실시 해주기위해 형변환을 해줘야 함
App.java
ㄴ loadCsv() 메서드를 이용하도록 하고, 각 파일에 대한 정보와 해당 데이터를 저장할 리스트, 그리고 클래스 타입을 인자로 전달하도록 함
버그 잡기
Member.java
Board.java
Item.java
ㄴ Item.itemId를 항상 현재까지 로드된 Item 객체들 중 가장 큰 no 값보다 1 큰 값으로 유지하는 것임
=> 이를 통해 새로 로드되는 Item 객체의 no 값을 중복되지 않도록 보장할 수 있음
Board.java
Board.java
ㄴ 인자값을 넘겨주는 생성자를 사용하기 위해 코드 변경
=> Member, Item 클래스도 동일하게 적용