Java Mid 17 - Collection List 추상화하기
in Programming Language on Java
인터페이스 도입
순서가 있고, 중복을 허용하는 것이 리스트. MyArrayList, MyLinkedList는 내부 구현만 다를 뿐 같은 기능을 제공하는 리스트이다. 물론 내부 구현이 다르기 때문에 상황에 따라서 성능은 달라진다. 핵심은 사용자 입장에서 보면 같은 기능을 제공한다. 이 둘의 공통 기능을 뽑아서 추상화를 해보면 다형성을 활용한 다양한 이점을 얻는다.
package collection.list;
public interface MyList<E> {
//list가 제공하는 기능
int size();
void add(E e);
void add(int index, E e);
E get(int index);
E set(int index, E element);
E remove(int index);
int indexOf(E o);
}
데이터를 앞에서 추가하거나 삭제하는 일이 많다면 MyArrayList 보다는 MyLinkedList를 사용하는 것이 훨씬 효율적이다. 구체적인 클래스에 의존하게 되면 의존을 하는 코드를 다 수정해야 하는 문제점이 있다. 그래서 구체적인 클래스에 의존하기 보다는 추상적인 클래스인 인터페이스에 의존하는 것이 더 바람직하다.
package collection.list;
//클라이언트 코드
public class BatchProcessor {
//의존성 주입
private final MyList<Integer> list;
//생성자 주입
public BatchProcessor(MyList<Integer> list) {
this.list = list;
}
public void logic(int size) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
list.add( 0, i );
}
long endTime = System.currentTimeMillis();
System.out.println( "크기: " + size + "계산 시간" + (endTime - startTime) + "ms" );
}
}
- 어떤 MyList list의 구현체를 선택할 지는 실행 시점에 생성자를 통해서 결정된다.
- 생성자를 통해서 MyList의 구현체가 전달된다.
- MyArrayList의 인스턴스가 들어올 수도 있고, MyLinkedList의 인스턴스가 들어올 수도 있다.
- 이것은 BatchProcessor의 외부에서 의존관계가 결정 되어서 BatchProcessor 인스턴스에 들어오는 것이다.
- 마치 의존관계가 외부에서 주입되는 것 같다고 해서 이것을 의존관계 주입이라고 한다.(Dependency Injection)
성능테스트
package collection.list;
public class BatchProcessorMain {
public static void main(String[] args) {
MyArrayList<Integer> list = new MyArrayList<>();
BatchProcessor processor = new BatchProcessor( list );
processor.logic( 50_000 );
}
}
package collection.list;
public class BatchProcessorMain {
public static void main(String[] args) {
MyList<Integer> list = new MyLinkdeList<>();
BatchProcessor processor = new BatchProcessor( list );
processor.logic( 50_000 );
}
}
런타임시 ArrayList, LinkedList를 사용할지 결정한다. 성능테스트 결과는 LinkedList가 훨씬 더 빠르다는 결과를 확인할 수 있다.
Reference
인프런 김영한님의 자바강좌 + 나의 뇌