设计模式思考:依赖
钻研了几个设计模式后,发现对一个名词的意义逐渐清晰起来,这个名词就是:依赖。
依赖,我的理解是,当为实现某功能的时候,你就已经开始依赖这些代码了。就比如下面的简单几句代码:
<?php
$str = 'First';
$str = strtolower($str);
echo $str;
?>
// 结果
// first
简单几句代码,也存在着几处依赖,第一行的赋值语句,它是将一个固定的字符串赋给了变量$str;第二行将变量$str全部变为小写,依赖strtolower函数,第三行是打印,依赖于echo。现在我们来逐一进行分析:
首先,第一行,由于$str依赖于等号后面的'First',所以它就此固定,很难在运行时改变了,这就是依赖;
然后,第二行,我们依赖于函数strtolower将变量$str全部字母变为小写,由于这个时候我们的需求是将字符串变为小写,而这个函数是由系统提供的,所以此时的依赖就很可靠,变化就不会很大;
最后,我们选择用echo打印出这个字符串,它就只能实现打印功能了,如果想为其他系统提供调用则不能实现。
这里就有一些依赖,但是其中有可靠的依赖(第二行),和不可靠的依赖(第一行,第三行)。而在我们的现实生活中,变化是不可避免的,不可靠的依赖将会导致系统难以维护,比如如上,我想根据我输入的字符得到不同的小写语句,就需要变动'First',当然在这里简单的两句话,变动看起来很容易,所以大家都会觉得没关系,改改就好了,但是如果这一句话,关联了整个系统,那么这个改动很有可能就会变成灾难性的。比如说第二句的strtolower函数,如果系统中多次调用(很多地方依赖于这个函数 ),万一这个函数又可以更改(一种假设,或者这里可以改成自己写的函数),那么这将导致系统整个出错,或者瘫痪。所以,在我们写程序的时候,我们的依赖最好就是可靠的,而可靠的是什么呢?那就是抽象,是接口!为什么呢?比如说,在生活中,你想上网,这个时候你就需要找台电脑上网,那么你就依赖了这台电脑,如果这台电脑坏了,可能你这个时候就上不了网了,但是如果你说,你要用电脑上网(当然在现实生活中不大可能用虚拟的电脑上网),那么这个时候就没问题了,为什么呢,因为电脑就是用来上网的(当然是连了网的),这是它的基本功能,它是抽象的,任何电脑都要实现这个功能,所以如果你说我要用电脑上网,这个肯定就没错了(除非哪一年电脑不能用来上网了,不过这个好像不大可能),这就是依赖于抽象,而这个就是很可靠的,因为它定义了一个接口(一个接口就是一个协议,实现了这个接口就必须遵循这个协议),而且它没用任何行为,所以它不会出错,这就是为什么我们常说的依赖于抽象。
刚刚提到的用电脑上网的这个事,如果你选择用你自己的电脑来上网,万一它坏了它就上不了网了,这个就是依赖的问题,这个时候如果我们转移依赖的对象,我们转移到另一个对象上,可以给你提供电脑的地方,比如说你的公司,一般来说公司可以保证给你提供一台可以上网的电脑,不会出错,这个时候你就不依赖具体的电脑了,你的依赖对象就转移为公司了,而它比你的电脑就可靠多了,这个就是依赖注入,就是当你想使用某资源的时候,你不是主动去获取那个对象,而是由另一个容器来提供给你,那么就可以接触你对这个对象的依赖,而这个容器而相对可靠,就达到了解耦的目的,灵活性就更强了。
对于工方法厂模式:它将对某对象的依赖转移到工厂里,由工厂来提供它创建方法,就如同上面的需要电脑上网的例子,达到解耦的目的;
对于命令模式:将对具体的一些方法,行为的依赖转移为对Invoker的execute方法的依赖,这样所有的被抽象为command对象的行为都可以由invoker来控制执行;
对于策略模式:是将对某对象的某方法的依赖内部进行转移,该方法可以根据不同的实现者来实现具体的方法,这样这个对象就不会因为某个方法有问题的时候而头疼了,可以很方便的进行更换;
对于外观模式:是将对子系统的依赖转移到高层组件上,我们就不需要去了解子系统的复杂功能了,只需要和高层组件打交道就可以了;
这就是我总结的一些关于依赖的知识,希望大家有意见,有问题多提出讨论讨论。