对接口和事件概念的深究

1.对于接口,个人认为更多的解决依赖颠倒。

接口的作用,1:可以解耦,我个人认为更确切的是,接口可以让依赖关系颠倒,原来是a和b的关系(a依赖b),变成了a和c(a定义c),b和c的关系(b依赖c),其中c是接口,通过中间层c,间接让b依赖a,有点控制反转的味道。 2.接口,定义类的某些方法不能更改方法名和方法传入的参数。

工作顺序的颠倒: 两个人合作做一个功能,A和B分别做2个模块,A是消费方,B是生产方,原来的先后顺序为: B生产出来一个方法,告诉A调用这个方法,来消费B生产的方法,

变成了:A定义个接口C,然后A使用C接口里面的方法实现了自己的功能,然后把C接口扔给B,让B去实现这个接口。

由生产方做主导的工作顺序,转变成消费方做主导的工作顺序。

详细的请看:http://www.fancyecommerce.com/2016/07/01/%e5%af%b9%e6%8e%a5%e5%8f%a3%e7%9a%84%e8%a7%81%e8%a7%a3-yii2/

2. 关于事件:

事件给人感觉很啰嗦,下面举个例子:
在电商系统加入购物车功能中,定义
A .为加入购物车,把产品的信息写入到购物车表中。
A 完成了后,老板说,加入购物车功能中得加入一个log记录功能,然后程序猿在原来的文件中加入了
B 日志功能
后来,老板说,加入购物车扣库存,程序猿在原来的文件中加入了功能C,扣产品库存
后来,老板说,加入优惠券,程序猿在原来的文件中加入了D功能
a,B,C,D功能都在一个文件中,后期很难维护。

升级模式:

分为购物车模块A,log模块B,产品模块C,优惠券模块D
让BCD三个模块实现对应的方法,然后给予A,然后A 实现购物车模块的加入购物车

也就是说,A需要等BDC三个模块完成,然后A才能完成,也就是说A依赖于BCD

继续升级:

A做了购物车模块,然后抛出事件,然后执行事件,后续如果有BCD想要添加功能,直接在事件触发前绑定事件就可以
这样,这样通过事件的配置文件,实现了解耦,也就是A的功能不依赖于BCD来,A 只需要抛出事件,然后BCD绑定过去,然后A触发即可,
这样A不依赖于BCD了。A可以先完成工作,然后,BCD的事件函数做好后,绑定上就可以,
而且在使用购物车模块的时候,我有很多事件,如果我想使用B日志功能,我就绑定上去,如果不使用我就不绑定,
这样就可以在不同的场景下面,有不同的购物车功能。

在上面,我们可以看到,每次添加事件,对于A来说,还是要更该A里面的内容,绑定事件。
我们进行下面的思考:

我是一个电商的开发商,你是一个我的系统的使用者,还是老样子啊,我的库包你是不能改动的
但是你又想改动我的功能
我在我的库包中,做了一个加入购物车的功能,请问,你如何做到不改动我的文件的前提下,在加入购物车这个动作中,添加你的一个功能呢,譬如你想在加入购物车的时候,添加一个日志记录功能。

解决办法:还是依赖注入,依赖的是配置文件,在配置文件中加入事件,我在做加入购物车的功能的时候,就想到了肯定很多人想在这里加代码,哪里我就提前部署好了事件,
通过配置文件中的事件配置,来绑定事件执行。
如果你想在加入购物车这个动作中加入你的代码,你可以做一个事件,然后在配置中加入你写的事件配置就可以了,对吧?
你没有改动我的系统文件,你改动的是配置文件。

总结:
接口:是为了解决依赖关系,由A依赖B,变成了,A定义接口,让B依赖接口,间接实现B依赖A
事件:A依赖BCD,变成了A定义事件,让BCD依赖事件,间接实现了让BCD依赖A,
配置文件注入:通过配置文件注入到组件的初始化中,可以在配置文件中添加事件配置,间接实现了 更改系统功能,但是不改动系统文件内容。

yii2 关于helper类 ArrayHelper::merge()方法的介绍

yii\helpers\ArrayHelper::merge()

在web/index.php入口文件就可以看到这个方法:

譬如:

$config = yii\helpers\ArrayHelper::merge(
    # yii2  common config
  require(__DIR__ . '/../../common/config/main.php'),
    require(__DIR__ . '/../../common/config/main-local.php'),
    # yii config
  require(__DIR__ . '/../config/main.php'),
  require(__DIR__ . '/../config/main-local.php'),
  # yii fecshop config
  require(__DIR__ . '/../../vendor/fancyecommerce/fecshop/config/fecshop.php'),
  # yii fecshop appfront config
  require(__DIR__ . '/../../vendor/fancyecommerce/fecshop/app/appfront/config/appfront.php'),
  # third people  config
  
  # user second develop config.
  
  require(__DIR__ . '/../config/fecshop_local.php')
    

);
$config['homeUrl'] = $homeUrl;
$application = new yii\web\Application($config);

需要注意的是ArrayHelper::merge方法,合并后的数组结果是什么:

下面通过例子讲解:

$arr1 = [
  'name' 	=> 'terry',
  'age'	=>	15,
  'friend'=> [
    'zhangsan','lisi'
  ],
  'work' =>[
    'aa'	=> 11,
    'bb'	=> ['aa','bb'],
  ],

];


$arr2 = [
  'name' 	=> 'water',
  'age'	=>	22,
  'friend'=> [
    'zhangsan','wangwu'
  ],
  'work' =>[
    'cc'	=> ['77','bb'],
    'aa'	=> 22,
  ],

];


$arr3 = yii\helpers\ArrayHelper::merge($arr1,$arr2);

$arr3的值为:

array(4) { [“name”]=> string(5) “water” [“age”]=> int(22) [“friend”]=> array(4) { [0]=> string(8) “zhangsan” [1]=> string(4) “lisi” [2]=> string(8) “zhangsan” [3]=> string(6) “wangwu” } [“work”]=> array(3) { [“aa”]=> int(22) [“bb”]=> array(2) { [0]=> string(2) “aa” [1]=> string(2) “bb” } [“cc”]=> array(2) { [0]=> string(2) “77” [1]=> string(2) “bb” } } }

 

可以看到这个数组的作用:

1.如果key是数字,那么value就会进行数组合并,如果值相同,不会覆盖,会出现两个相同值的数组元素,譬如[1,2]和[2,3]通过merge函数合并的结果为[1,2,2,3].

2.如果数组的key不是数字,而且数组里面的value不是数字,则value会被覆盖掉

譬如[‘aa’ => ‘xxx’]和[‘aa’=>’yy’]  merge函数后的结果为[‘aa’=>’yy’],

3.如果数组的key不是数字,而value是数组(数组的key是数字),则会进行数组合并。

4.如果数组的key不是数字,而value是数组(数组的key不是数字),则value数组中的key回合第二个步骤那样处理。

 

具体可以自己琢磨,因此在使用这个方法的时候,要想key覆盖,key一定要用字符串,就和变量定义一样。