概念:本文中的“分解依賴” 是指對部分不滿足我們要求的類和方法進行依賴分解,通過裝飾器來達到我們需要的功能。
正文:正如下面代碼所示,如果你要在你的代碼中加入單元測試但有一部分代碼是你不想測試的,那麼你應用使用這個的重構。下面的例子中我們應用靜態類來完成某些工作,但問題是在單元測試時我們無法mock靜態類,所以我們只能引入靜態類的裝飾接口來分解對靜態類的依賴。從而我們使我們的調用類只需要依賴於裝飾接口就能完成這個操作。
namespace LosTechies.DaysOfRefactoring.BreakDependencies.Before
{
public class AnimalFeedingService
{
private bool FoodBowlEmpty { get; set; }
public void Feed()
{
if (FoodBowlEmpty)
Feeder.ReplenishFood();
// more code to feed the animal
}
}
public static class Feeder
{
public static void ReplenishFood()
{
// fill up bowl
}
}
}
重構後代碼如下,我們添加一個接口和一個實現類,在實現類中調用靜態類的方法,所以說具體做什麼事情沒有改變,改變的只是形式,但這樣做的一個好處是增加了了代碼的可測試性。在應用了分解依賴模式後,我們就可以在單元測試的時候mock一個IFeederService對象並通過AnimalFeedingService的構造函數傳遞給它。這樣就可以完成我們需要的功能。
namespace LosTechies.DaysOfRefactoring.BreakDependencies.After
{
public class AnimalFeedingService
{
public IFeederService FeederService { get; set; }
public AnimalFeedingService(IFeederService feederService)
{
FeederService = feederService;
}
private bool FoodBowlEmpty { get; set; }
public void Feed()
{
if (FoodBowlEmpty)
FeederService.ReplenishFood();
// more code to feed the animal
}
}
public interface IFeederService
{
void ReplenishFood();
}
public class FeederService : IFeederService
{
public void ReplenishFood()
{
Feeder.ReplenishFood();
}
}
public static class Feeder
{
public static void ReplenishFood()
{
// fill up bowl
}
}
}
總結:這個重構在很多時候和設計模式中的一些思想類似,使用中間的裝飾接口來分解兩個類之間的依賴,對類進行裝飾,然後使它滿足我們所需要的功能。