의존 객체 주입 (Dependency Injection)을 프레임 워크로 제공하는 Dagger, Guice, Spring 등 있는데 한국의 대부분 자바 개발자에게 친숙하게 다가오는 것은 스프링 프레임워크일 것이다.
스프링을 생각해보면 인터페이스 기반으로 클래스 레벨에서는 의존하지 않고 런타임 시 동적으로 주입받는 역할로 많이 사용되고 있다. 이처럼, 유연성을 확보하고 결합도를 낮춰 주는 등의 장점이 존재한다.
여기서 언급되는 정적 유틸리티 클래스, 싱글턴으로서 구현되면 위의 장점과 반대로 유연하지 못하고 결합도는 높아진다.
유일 객체로 사용된다고 하였을 때는 유연성에 대한 고려는 하지 않아도 되겠다.
.
이를 해소하기 위해 final 필드 제거하고 메서드를 통한 다형성을 제공할 수 있지만 멀티 스레드 환경에서 사용하기 어려우며, 사용하는 자원에 따라 동작이 달라지는 클래스에서는 적합하지 않다.
따라서 인스턴스 생성 시점에 사용에 필요한 자원을 넘겨주는 의존 객체 주입 패턴을 사용하자는 것이 Item 5의 주제이다.
의존 객체 주입에 알맞는 함수형 인터페이스 중 팩터리 메서드 패턴인 Supplier가 있다. 한정적 와일드 카드에 타입의 제한을 주어 하위타입이라면 무엇이든 생성해주는 유연성을 제공한다. 반면 의존성이 많아지면 코드가 복잡해질 수 있는데 이를 위에서 언급한 Framework를 통해 어느정도 해소하고 있다.
아래는 Supplier를 이용하여 "자동차는 사람이라면 탈 수 있다"는 예제이다.
사람 인터페이스
public interface Person {
String getName();
}
남자
public class SupplierBoy implements Person {
private final String name = "supplier boy";
@Override
public String getName() {
return name;
}
}
여자
public class SupplierGirl implements Person {
private final String name = "supplier girl";
@Override
public String getName() {
return name;
}
}
선생님
public class SupplierTeacher implements Person {
private final String name = "supplier teacher";
@Override
public String getName() {
return name;
}
}
자동차
public class SupplierCar {
private final Supplier<Person>[] people;
public SupplierCar(Supplier<Person> ... people) {
System.out.println("======================================================");
this.people = people;
Arrays.stream(people).forEach(p -> {
System.out.println(p.get().getName() + "이/가 탑승했습니다.");
});
}
public void ride(Supplier<Person> ... people) {
Arrays.stream(people).forEach(p -> {
System.out.println(p.get().getName() + "이/가 탑승했습니다.");
});
}
public void leave(Supplier<Person> ... people) {
Arrays.stream(people).forEach(p -> {
System.out.println(p.get().getName() + "이/가 내렸습니다.");
});
}
}
실행 결과
public class Main {
public static void main(String[] args) {
// Supplier + 가변 인자 예제
SupplierCar supplierCar = new SupplierCar(SupplierBoy::new, SupplierGirl::new);
supplierCar.ride(SupplierTeacher::new);
supplierCar.leave(SupplierBoy::new, SupplierTeacher::new);
}
}
예제 코드
GitHub - VenusIM/Study_Record
Contribute to VenusIM/Study_Record development by creating an account on GitHub.
github.com
'Study with group' 카테고리의 다른 글
[Item 7] 다 쓴 객체 참조를 해제하라 (1) | 2023.01.29 |
---|---|
[Item 6] 불필요한 객체 생성을 피하라 (0) | 2023.01.23 |
정적 유틸리티 클래스 (Static Utility Class) (0) | 2023.01.09 |
[Item 4] 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2023.01.09 |
팩터리 패턴 (Factory Pattern) (1) | 2023.01.09 |
댓글