控制反转(IoC, Inversion of Control),依赖注入(DI, Dependency Injection)是在面向对象编程中经常碰到的专业术语。很多朋友可能在百度之后,便浅尝辄止,没有深入理解这两种思想的精髓。我们在查找IoC的含义的过程中,可能 见过这句通俗的解释:你呆着别动,到时我会找你。这句解释到底应该如何去理解呢?下面,我们结合具体的业务场景和其实现方式的研究,来对IoC以及DI做一个比较详细的解释,希望能够对初学者有所启发。
一. 一个常见的业务场景
在移动互联网APP中,几乎都要使用推送信息的功能,如:我们经常会在周五晚上收到APP的推送消息,这样的消息形式包括APP自有推送(通知栏),短信推送(短信中的通知类消息,有可能被过滤),邮件推送,微信推送,甚至以后还可能拓展到穿戴式设备推送,消息的形式非常丰富。而推送的消息中,主要是一些商品推荐类,内容推荐类或者系统通知类的内容。假定现在公司要你负责这部分推送功能的架构和实现,你应该如何去设计呢?
这个业务场景可以说在每个移动互联网公司都会遇到。假如该公司的名称为XM,负责实现该部分功能的小组中有三位研发成员,分别是:小A,小B和小C。如何对该功能系统进行整体架构,使得开发效率最高?我们可以围绕以下几个问题,进行逐步探讨:
- 如果只实现短信推送的功能,如何设计和实现?
- 怎么使系统保持可扩展性,减少研发人员的修改工作?
- 可以彻底省去对代码的修改吗?
我们围绕这三个具体的问题,来一步步实现和改进我们的系统。
二. 功能的设计实现与改进
2.1 程序实现V1.0
首先,短信推送的功能,要今天晚上开发上线。三个人一听就慌了,还有五个小时,顾不上考虑那么多了,先把功能开发出来再说。于是,三个人经过简单的讨论,将系统的实现架构设计如下:
根据系统设计,分工如下:由小A负责业逻辑控制模块LogicController的开发,此处简化为XM.LogicController.exe;由小B负责推送消息管理(PushMsgService),并集成到组件 XM.MsgService.dll中;由小C负责短信功能帮助类(SMSHelper),并提供组件XM.SMS.dll。
根据以上的设计和分工,不到一个小时,功能便做出来了。各自的代码如下:
小C的短信功能帮助类核心代码:
1 public class SMSHelper 2 { 3 public void Send(string message) 4 { 5 Console.Write("From SMS: " + message); 6 } 7 }
小B的消息管理模块核心代码如下:
1 public class PushMsgService 2 { 3 SMSHelper pushTool; 4 5 public PushMsgService() 6 { 7 pushTool = new SMSHelper(); 8 } 9 10 public void Push(string message) 11 { 12 pushTool.Send(message); 13 } 14 }
小A的业务集成模块的核心代码如下:
1 string message = "今日特价:创意城绿茶餐厅30元4人餐"; 2 MsgService.PushMsgService service = new MsgService.PushMsgService(); 3 service.Push(message);
三个人经过短暂的拼搏,终于完成了任务,顺利上线了产品。做完之后,三个人洋洋得意的push了代码,一块去街边撸串去了。当日,系统运行良好,无任何bug出现。第二天,相应的功能被移植到了公司的其他部门。如:后台编辑部开发的推送管理系统,也需要此功能;运营部开发的产品推荐系统,也需要此功能;人力资源部门的招聘管理系统,也需要此功能。短信消息推送的功能,在各个部门里面,被广泛的应用,都是采用ABC开发的这一套库去做的实现。
2.2 程序实现V2.0
有天,跟XM合作的短信服务商突然提高了合作的价格,每条短信要多收1分钱。于是,部门经理当机立断:立即研发自有推送功能。除非客户所处的地区网络及其不好,否则,一律采用自有推送功能进行消息推送。
接到这个需求之后,ABC便马不停蹄的开始工作了。不过,这次他们有点头疼了,因为他们之前的代码不仅在自己部门使用,而且在编辑部,运营部,人力资源部都有被使用。如果要修改,难道我要一个个去各个部门修改吗?怎么样使得此处的变化,产生最小的影响呢?这就是我们要研究的第二个问题。