分解依赖

重构分解依赖
本文介绍了一种重构技巧——分解依赖,通过引入装饰接口来减少类之间的直接依赖,提高代码的可测试性。具体做法是将静态类的方法调用封装进一个接口实现类中,使得调用者仅需依赖接口即可。

概念:本文中的“分解依赖” 是指对部分不满足我们要求的类和方法进行依赖分解,通过装饰器来达到我们需要的功能。

正文:正如下面代码所示,如果你要在你的代码中加入单元测试但有一部分代码是你不想测试的,那么你应用使用这个的重构。下面的例子中我们应用静态类来完成某些工作,但问题是在单元测试时我们无法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
        }
    }
}

总结:这个重构在很多时候和设计模式中的一些思想类似,使用中间的装饰接口来分解两个类之间的依赖,对类进行装饰,然后使它满足我们所需要的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值