본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 28일차 (2023-06-30) 자바 기초 DAY26_자바 프로그래밍_리팩토링: Factory Method 패턴(GoF), Information Expert 패턴(GRASP)_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 7. 1.
## 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.classfromCsv 메서드의 매개변수 유형인 String을 나타냄
=> factoryMethodclazz에서 정의된 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 클래스도 동일하게 적용