為什麼需要依賴注入

木宛城主發表於2024-10-07
為什麼需要“依賴注入”

Case 1

public class Foo {
  private Bar bar;
  public Foo() {
    bar = new Bar();
  }
  public void doSomething(int key) {
    String result = bar.getResult(key);
    //swithch result
  }
}

反模式 ,在建構函式中,初始化了合作類,導致:

• 外部使用者不知道 Foo 裡面還依賴了 Bar

• 無法對Bar單元測試,體現在 bar.getResult() 返回真實值,如果和網路、資料庫、IO 打交道的話,這是一個很耗時的動作

Case 2

public class Foo {
  private Bar bar=new Bar();
  public Foo(){
  }
  public void doSomething(int key){
  String result = bar.getResult(key);
  //swithch result
  }
}

反模式,雖然沒有在建構函式中初始化 Bar 物件,但在欄位中直接初始化了 Bar 物件,問題和上面一樣

Case 3 使用 Guice 來對依賴進行管理

public class Foo {
  private Bar bar ;
  @Inject
  public Foo(Bar bar) {
  this.bar = bar;
  }
  public String doSomething(int key) {
  return bar.getResult(key);
  }
}

對於使用 Foo 的使用者而言,一眼就知道 Foo 內部需要 合作類 Bar, 明白了 Foo 的職責,同時 @Inject 將依賴物件注入,解耦的同時還方便測試

public class TestCase {
  @Mock
  private Bar bar;
  @Before
  public void before(){
  MockitoAnnotations.initMocks(this);
}
  @Test
  public void test(){
  //Arrange
  when(bar.getResult(eq(1))).thenReturn("jack");
  Foo foo=new Foo(bar);
  //Action
  String result = foo.doSomething(1);
  //Assert
  Assert.assertEquals("jack",result);
  }
}

上面可以看到,MockBar 物件,Bar 物件的 getResult() 可能是一個比較耗時的功能,所以對它進行了Stub,同時 Foo 不依賴真實的 Bar 物件。

相關文章