## 21. 인터페이스를 이용하여 List 사용 규칙 정의하기
- 목록 관리 객체의 사용 규칙을 인터페이스 정의
- List 인터페이스 정의
- ArrayList, LinkedList에 List 인터페이스 적용
- MemberHandler와 BoardHandler에 적용
- List 구현체를 생성자를 통해 주입: DI(Dependency Injection) 적용
인터페이스를 이용하여 List 사용 규칙 정의하기
목록 관리 객체의 사용 규칙을 인터페이스 정의
List 인터페이스 정의
ㄴ List 인터페이스 정의
ㄴ java.util.LinkedList 를 참고하여 비슷하게 만들기 위해 java 17 api 검색
ㄴ java.base > java.util
ㄴ Interface > List 참고
ㄴ add 메서드는 boolean 타입
ㄴ get 메서드는 파라미터로 int 타입을 받음
ㄴ toArray() 라는 메서드가 목록을 출력함
ㄴ remove(int index) => 번호를 이용해서 삭제
ㄴ remove(Object o) => 객체를 받아서 삭제
List.java
ㄴ java.util.LinkedList 를 참고하여 List interface 를 정의
ArrayList, LinkedList에 List 인터페이스 적용
ArrayList 에 List 인터페이스 적용
ArrayList.java
ㄴ ArrayList 클래스에 List 인터페이스를 적용
ArrayList.java
ㄴ @Override 어노테이션을 이용해서 해당 메서드가 수퍼클래스의 메서드를 재정의한 것인지, 인터페이스의 메서드를 구현한 것인지 검사
ArrayList.java
ㄴ 메서드 명이 다름
ArrayList.java
ㄴ 리턴 타입이 다름
ArrayList.java
ㄴ 파라리터명은 달라도 됨
ArrayList.java
=>
ArrayList.java
ㄴ List 인터페이스에서 toArray(); 로 정의되어있음
ArrayList.java
ㄴ List 인터페이스에서 접근제어자가 public 으로 선언되어있으므로 재정의할 때에도 public 을 써줘야 함
ArrayList.java
=>
ArrayList.java
ㄴ get 메서드의 파라미터가 List 인터페이스에서 int 타입으로 정의되어있음
ArrayList.java
ㄴ index 가 0 보다 작거나 length(배열 개수) 보다 크다면 null 리턴하도록 함
ArrayList.java
ㄴ index 가 유효한 값이라면 해당 번째의 Object 배열을 리턴함
ArrayList.java
ㄴ List 인터페이스에서 delete 역할을 하는 메서드의 이름이 remove 로 정의되어있음
ㄴ remove 의 파라미터 타입이 두 가지가 있으므로 int 타입의 파라미터를 받고 리턴타입이 Object인 remove 메서드도 추가해줌
=>
ArrayList.java
ㄴ Object 타입의 파라미터를 받는 remove 를 복사해서 붙여넣은 후 수정
=>
ArrayList.java
ㄴ indexOf 를 사용하는 대신 index 가 유효한 숫자인지 검증하는 코드 추가
ArrayList.java
ㄴ 삭제할 객체를 old 라는 Object 타입의 변수에 저장한 후 삭제가 완료되면 삭제할 객체 old 를 리턴
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html
ㄴ List Interface 를 참고함
ㄴ 이전 요소를 리턴한다고 나와있으므로 참고하여 코드 작성한 것
ArrayList.java
ㄴ 해당 코드 반복되므로 메서드로 분리해줌
=>
ArrayList.java
ㄴ 내부에서만 사용할 것이므로 private 으로 정의해줌
ㄴ index 가 유효한 값인지 검사해주는 메서드
=>
ArrayList.java
ㄴ 코드를 간단하게 줄여줄 수 있음
ArrayList.java
==> 해당 코드 LinkedList 에도 적용해주기
LinkedList.java
ㄴ length 대신 size 로 선언되어있기 때문에 length -> size 로 변경해줌
LinkedList 에 List 인터페이스 적용
LinkedList.java
ㄴ LinkedList 에 List 인터페이스 적용시킴
LinkedList.java
=>
ㄴ List 인터페이스에 toArray() 로 정의되어있으므로 변경해줌
LinkedList.java
ㄴ @Override 어노테이션을 이용해서 해당 메서드가 수퍼클래스의 메서드를 재정의한 것인지, 인터페이스의 메서드를 구현한 것인지 검사
LinkedList.java
ㄴ List 인터페이스에 Object 타입의 파라미터를 담아와서 추가하는 메서드는 boolean 타입으로 정의되어있음
=> 추가가 잘 되었으면 true 를 리턴
LinkedList.java
=>
LinkedList.java
ㄴ List 인터페이스에서 toArray(); 로 정의되어있음
LinkedList.java
=>
LinkedList.java
ㄴ List 인터페이스에서 toArray(); 로 정의되어있음
ㄴ 파라미터 타입은 int
LinkedList.java
ㄴ index 값 유효성 검사
LinkedList.java
ㄴ index 값을 받아와서 index 가 유효한 값이라면 cursor 위치를 첫 노드로 변경해줌
ㄴ cursor 위치를 다음으로 하나씩 index 까지 이동시킨 후 cursor 위치의 value 리턴
LinkedList.java
ㄴ index 값의 유효성을 따져서 index 값을 이용하여 삭제하는 메서드
ㄴ 리턴타입이 boolean 이고 Object 타입의 파라미터를 사용하는 remove 메서드를 가져와서 수정
=>
LinkedList.java
while (cursor != null) {
if (cursor.value.equals(value)) {
ㄴ 해당 코드 제거
=>
LinkedList.java
=>
LinkedList.java
public Object remove(int index) {
if (!isValid(index)) {
return null;
}
Node prev = null;
Node cursor = this.head;
// 삭제하려는 값이 있는 노드까지 이동한다.
for (int i = 0; i < index; i++) {
prev = cursor; // 다음 노드로 이동하기 전에 현재 커서가 가리키는 노드를 prev에 보관한다.
cursor = cursor.next; // 커서를 다음 노드로 이동시킨다.
}
// 삭제할 값을 리턴할 수 있도록 보관한다.
Object old = cursor.value;
// 삭제할 노드가 시작 노드라면
if (prev == null) {
head = cursor.next;
// 삭제할 노드가 끝 노드라면
if (head == null) {
tail = null;
}
} else if (cursor.next == null) { // 삭제할 노드가 끝 노드라면
tail = prev;
tail.next = null;
} else {
// 중간 노드라면, 다음 노드의 주소를 이전 노드에 저장한다.
prev.next = cursor.next; // 현재 커서의 다음 노드를 현재 커서의 이전 노드와 연결한다.
}
size--;
// 가비지 객체를 초기화시켜서 가비지가 인스턴스를 가리키지 않도록 한다.
cursor.next = null;
cursor.value = null;
return old;
}
ㄴ 삭제할 객체를 old 라는 Object 타입의 변수에 저장한 후 삭제가 완료되면 삭제할 객체 old 를 리턴
MemberHandler 와 BoardHandler 에 List 인터페이스 적용
List 구현체를 생성자를 통해 주입 : DI(Dependency Injection) 적용
ㄴ BoardHandler 수정 후 MemberHandler, ItemHandler 도 동일하게 적용
BoardHandler.java
ㄴ List 인터페이스를 사용하기 위해 선언해 준 후 import 해줌
BoardHandler.java
ㄴ getList -> toArray()
BoardHandler.java
ㄴ retrieve -> get
번호를 이용해 Board 를 가져오는 findBy(int no) 메서드 선언
BoardHandler.java
ㄴ 리스트를 toArray() 메서드를 사용하여 Object 배열로 변환
ㄴ arr 배열의 각 요소를 순회하면서 obj에 저장하고 obj를 Board 타입으로 캐스팅하여 b에 저장
ㄴ b의 getNo() 메서드를 호출하여 해당 게시글의 번호를 가져와 주어진 no 값이 일치하는지 확인
ㄴ 일치한다면, 해당 게시글 b를 반환
ㄴ 반복이 모두 완료되어도 일치하는 게시글을 찾지 못하면 null을 반환
BoardHandler.java
=>
BoardHandler.java
ㄴ 번호를 이용해 Board 를 가져오는 findBy(int no) 메서드 이용
BoardHandler.java
=>
BoardHandler.java
ㄴ 번호를 이용해 Board 를 가져오는 findBy(int no) 메서드 이용
List 인터페이스에 size() 메서드 정의 추가
ㄴ ArrayList 클래스에 size() 메서드 추가
ArrayList.java
ㄴ LinkedList 클래스에 size() 메서드 추가
LinkedList.java
printBoards() 메서드를 list.size() 를 이용한 for 문으로 변경
BoardHandler.java
findBy(int no) 메서드를 list.size() 를 이용한 for 문으로 변경
BoardHandler.java
=> MemberHandler, ItemHandler 도 동일하게 적용
MemberHandler.java
ㄴ List 인터페이스를 이용하기 위해
=> MemberHandler, ItemHandler 도 동일하게 적용
App.java
ㄴ MemberHandler, ItemHandler, BoardHandler, NoticeHandler 등의 핸들러 객체에서 각각의 핸들러에서 사용할 리스트를 생성하기 위한 코드
ㄴ ArrayList는 내부적으로 배열을 사용하여 리스트를 구현하는 것으로, 데이터의 접근과 순차적인 추가/삭제 연산에 빠른 성능
=> MemberHandler와 ItemHandler와 같이 데이터의 추가/삭제보다는 조회가 빈번한 경우에 적합
ㄴ LinkedList는 각 요소들이 링크로 연결되어 있는 형태로 리스트를 구현하는 것으로, 데이터의 추가/삭제 연산에 빠른 성능
=> LinkedList는 요소의 추가/삭제가 빈번한 경우에 적합