依赖注入
场景出发 假设存在如下游戏场景: 1:角色可以装备木剑,铁剑,魔剑3种装备,分别对怪物造成20HP,50HP,100HP伤害(未佩戴装备则无法攻击); 2角色可以向怪物攻击,一次攻击后损失角色所佩戴装备的HP伤害,当HP损失完毕后,怪物死亡; 不假思索地我会写出如下的代码: 1 class Monster 2 { 3 public string Name { get; set; } 4 public int HP { get; set; } 5 /// <summary> 6 /// 怪物被攻击后提示 7 /// </summary> 8 /// <param name="loss">武器造成的HP伤害损失</param> 9 public void Warn(int loss) 10 { 11 if (HP <= 0) 12 { 13 Console.WriteLine($"怪物{Name}已经死亡"); 14 return; 15 } 16 17 HP -= loss; 18 19 Console.WriteLine($"怪物{Name}受到{loss}HP伤害"); 20 21 if (HP <= 0) 22 { 23 Console.WriteLine($"怪物{Name}被打死了"); 24 } 25 } 26 } 1 class Role 2 { 3 public string Name { get; set; } 4 public string Weapon { get; set; } 5 /// <summary> 6 /// 武器攻击 7 /// </summary> 8 /// <param name="monster">攻击的怪物对象</param> 9 public void Attack(Monster monster) 10 { 11 if (Weapon == "WoodenSword") 12 { 13 Console.WriteLine($"{Name}用木剑攻击了{monster.Name}"); 14 monster.Warn(25); 15 } 16 17 else if (Weapon == "IronSword") 18 { 19 Console.WriteLine($"{Name}用铁剑攻击了{monster.Name}"); 20 monster.Warn(50); 21 } 22 else if (Weapon == "MagicSword") 23 { 24 Console.WriteLine($"{Name}用魔剑攻击了{monster.Name}"); 25 monster.Warn(100); 26 } 27 else 28 { 29 Console.WriteLine($"{Name}没有武器,无法攻击"); 30 } 31 } 32 } 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var monster = new Monster() 6 { 7 Name = "沼泽首领", 8 HP = 80 9 }; 10 var role = new Role() 11 { 12 Name = "狂战士",13 Weapon="IronSword" 14 }; 15 role.Attack(monster); 16 role.Weapon = "WoodenSword"; 17 role.Attack(monster); 18 role.Weapon = "MagicSword"; 19 role.Attack(monster); 20 21 Console.ReadKey(); 22 } 23 } 相信不止我一个人会这样写,因为它能快速的"完美的"实现上述功能 回过头来再仔细观察这段代码,就感觉像在看一段"直肠子",所有的逻辑算法都集中到了一个管道上,只要有需求或逻辑上的的变化,那么就得直接去修改业务类 改进分析 分析上述代码,它严重违背了开闭原则(OCP,Open Closed Principle,即我们的程序是可扩展的,在遇到新的需求或者变化的时候,是不需要对原有类有任何修改的),显然上述代码无法适应新的需求.随便一点需求的变化,就必须去修改具体类,对此我们做出如下简单的修改: 将Weapon抽象出来,? 使Role对Weapon的依赖,转为对Weapon抽象的依赖,代码如下 1 public interface IWeaponStrategy 2 { 3 void WeaponAttack(Monster monster); 4 } 1 public class WoodenSwordStrategy : IWeaponStrategy 2 { 3 public void WeaponAttack(Monster monster) 4 { 5 Console.WriteLine("木剑攻击"); 6 monster.Warn(20); 7 } 8 } 9 public class IronSwordStrategy : IWeaponStrategy 10 { 11 public void WeaponAttack(Monster monster) 12 { 13 Console.WriteLine("铁剑攻击"); 14 monster.Warn(50); 15 } 16 } 17 18 public class MagicSwordStrategy : IWeaponStrategy 19 { 20 public void WeaponAttack(Monster monster) 21 { 22 Console.WriteLine("魔剑攻击"); 23 monster.Warn(100); 24 } 25 } 1 public class Monster 2 { 3 public string Name { get; set; } 4 public int HP { get; set; } 5 6 /// <summary> 7 /// 怪物被攻击后提示 8 /// </summary> 9 /// <param name="loss">武器造成的HP伤害损失</param> 10 public void Warn(int loss) 11 { 12 if (HP <= 0) 13 { 14 Console.WriteLine($"怪物{Name}已经死亡"); 15 return; 16 } 17 18 HP -= loss; 19 20 Console.WriteLine($"怪物{Name}受到{loss}HP伤害"); 21 22 if (HP <= 0) 23 { 24 Console.WriteLine($"怪物{Name}被打死了"); 25 } 26 } 27 } 1 class Role 2 { 3 public string Name { get; set; } 4 public IWeaponStrategy Weapon { get; set; } 5 public void Attack(Monster monster) 6 { 7 Weapon.WeaponAttack(monster); 8 } 9 } 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var monster = new Monster() 6 { 7 Name = "沼泽首领",13 Weapon=new IronSwordStrategy() 14 }; 15 role.Attack(monster); 16 role.Weapon = new WoodenSwordStrategy(); 17 role.Attack(monster); 18 role.Weapon = new MagicSwordStrategy(); 19 role.Attack(monster); 20 21 Console.ReadLine(); 22 } 23 } 结语 也许结束来的突兀,但是我想表述的东西已经接近尾声,其实最初我写了很多,什么各种注入的方式介绍,反射加配置文件等,甚至Unity框架的例子我都写了一个,但是真的越写越不痛快,因为这这篇文章越写越多的时候,我脑子里面的东西反而越来越少 依赖注入即控制反转: 起因:客户类或上端)(Role)依赖了服务类(Weapon)的细节(实例); 目的:降低程序耦合度 方式:依赖抽象 延伸:在上端仍有细节(需要实例武器抽象) 本质:一个转移依赖的过程 当你真的理解上述改进的过程,记住了它的本质,你就不会被不同包装的依赖注入所困扰 ? 推荐博客:依赖注入那些事儿 ? ?出自:博客园-半路独行 ?原文地址:https://www.cnblogs.com/banluduxing/p/9185142.html ?本文出自于http://www.cnblogs.com/banluduxing?转载请注明出处。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |