말 그대로입니다. 예를 들어, IronNougget의 생성자에 이름을 전달해야하는 상황이 생겼다고 치면, 아래처럼 IronNouget()을 생성하는 모든 코드를 직접 변경해주어야 겠죠? 만약 IronNuigget를 생성하는 곳이 10곳이라면 10곳을 모두 변경햊 주어야 합니다. 사용하는 곳이 많아질 수록 코드 변경애 번거롭고 리스크가 생깁니다.
class IronNugget(val name: String) {
...
}
// Axe클래스 내부에서 IronNugget 클래스를 생성하여 사용
class Axe {
val ironNugget = IronNugget("IronNougget")
...
}
// Shovel 클래스 내부에서 IronNugget 클래스를 생성하여 사용
class Shovel {
val ironNugget = IronNugget("IronNougget")
...
}
하지만 DI를 사용할 경우는 DI를 해주는 곳만 변경해 주면 됩니다.
object IronModule {
provide fun providesAxe(): Axe {
return Axe(providesIronNougget());
}
provide fun providesShovel(): Shovel {
return Shovel(providesIronNougget());
}
private fun providesIronNougget(): IronNougget {
return IronNougget("IronNougget")
}
}
다른 예는 IronNougget 클래스 대신에 다른 구현체를 사용할 경우입니다. 앱을 만들다 보면 구현 클래스자체를 아예 바꾸어야 하는 경우도 생깁니다. 이런 경우는 더 문제가 됩니다. 아래와 같이IronNougget가 인터페이스이고 구현 클래스를 교체해야 하는 상황에서도 차이점을 더 명확하게 볼 수 있습니다.
interface IronNuggeInterface
// 철광석 클래스
class IronNugget: IronNuggeInterface {
...
}
class AnotherIconNugget: IronNuggeInterface {
}
// 내부에서 직접 생성 - 구현체에 따라 사용하는 클래스에 변경사항이 생김.
class Axe {
val ironNugget: IronNuggeInterface = AnotherIconNugget()
...
}
class Shovel {
val ironNugget : IronNuggeInterface= AnotherIconNugget()
...
}
// DI 사용 - 구현체가 바뀌어도 사용하는 클래에는 변경사항이 없음.
class Axe(val ironNugget: IronNuggeInterface) {
}
class Shovel(val ironNugget: IronNuggeInterface) {
}