废话
1. 为了提升自己的学习效率,通过写博客的方式从被动学习转化为一定程度的主动学习。
2.有一件每天都能坚持做的事情,可能更让人有或者的感觉?
每天一篇学习笔记,立帖为证。
在读《单元测试的艺术》的绪论的时候,有很多不懂的名词,就去查了一下,一些印象深刻的就记了些笔记。
Mostly I stopped using property setters and am mostly using constructor injection.
什么是依赖注入(Dependency Injection)
依赖注入是用来实现代码的松耦合的一种模式。如果一个对象需要进行另一个对象的创建,管理等过程,这样就会带来一种紧耦合。
例子:在一个游戏里面,我是一个武士,我有一把剑,我拿剑攻击。
///剑的类
class Sword
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
///武士的类,会用到那把剑,所以在里面新建了一个剑的实体
class Samurai
{
readonly Sword sword;
public Samurai()
{
this.sword = new Sword();
}
public void Attack(string target)
{
this.sword.Hit(target);
}
}
///主函数,武士拿着剑去攻击别人
class Program
{
public static void Main()
{
var warrior = new Samurai();
warrior.Attack("the evildoers");
}
}
这里的武士就依赖于剑这个实体,是一种紧耦合。因为当我想给这武士换一把武器的时候。我需要去修改武士这个类的实现。
根据依赖倒置原则(DIP):高层模块不应该依赖于底层模块,二者都应该依赖于抽象。针对接口编程,不要针对实现编程。
这里Sword
类就是底层模块,而我们以上用的方法就属于针对实现的编程。
那应该怎么修改呢?
///剑的抽象 是武器
interface IWeapon
{
void Hit(string target);
}
///底层模块是剑,它应该依赖于武器这个抽象接口(继承,实现也是一种依赖关系)。
class Sword : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
- 属性注入
///高层模块 是武士,他也应该依赖于武器这个抽象接口(组合也是一种依赖关系)
///这就是一种属性注入(property injection),将武器作为武士的一种属性,通过特定函数来设置它
class Samurai
{
IWeapon weapon;
public Samurai() { }
public void SetWeapon(IWeapon weapon)
{
this.weapon = weapon;
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}
- 构造注入
///将武器作为武士的构造器的参数传入
class Samurai
{
readonly IWeapon weapon;
public Samurai(IWeapon weapon)
{
this.weapon = weapon;
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}
- 方法注入
class Samurai
{
public void Attack(string target, IWeapon weapon)
{
weapon.Hit(target);
}
}
以上就是实现依赖注入的三种方式
- Constructor Injection
- Setter or property Injection
- Method Injection
还有第四种,我还没有学到
- Service Locator Injection
还有这几种方式的优劣或者适用场景还有待学习。
参考:
https://softwareengineering.stackexchange.com/questions/177649/what-is-constructor-injection
https://blog.csdn.net/qq_34760445/article/details/82931002