以小说的笔法写的设计模式系列文章,你绝对看得懂![首发于公众号:"聊聊代码"]javascript
设计模式系列·王小二需求历险记(一)
设计模式系列·王小二需求历险记(二)
设计模式系列·封装、继承、多态
设计模式系列·初探设计模式之王小二的疑问
设计模式系列·Facade模式之MVC的烦恼
设计模式系列·Adapter 模式之如何优雅的使用别人的轮子
设计模式系列·类爆炸之Bridge模式
设计模式系列·工厂方法模式之 Code Review
设计模式系列·抽象工厂模式php
------华丽的分割线------java
现在的Web开发,各类框架风起云涌,势如破竹。设计模式
从国民第一的ThinkPhp到称霸全球的Laravel,这些框架有一个共同特征,都采用了MVC的架构模式。架构
没有任何意外,王小二的公司用Thinkphp来开发公司的主打产品。mvc
一天,小二刚到公司,正打算坐下来喝杯茶。框架
老大走了过来:“小二啊,如今有个新的需求。我们以前提交订单的模块,须要增长发送邮件的功能,你看看能不能实现?”post
小二想了想说:“没问题,最多3天搞定!”学习
看王小二成竹在胸的样子,老大满意的点了点头。ui
着手开干吧!小二打开熟悉的IDE,找到提交订单模块的Controller。
OMG!不看不知道,一看吓一跳,这个Controller的代码居然接近2000行。
由于用户提交订单时,会与其余模块进行交互,须要的数据也比较复杂。
只见此Controller,从Model层各类拿数据,而后各类逻辑处理,怪不得代码到了将近2000行。
“哎,这2000行代码,看着就头疼,可以让我怎么写啊”...小二叹气道。
“要再也不去请教下C哥?”
小二找到C哥,详细的描述了他的问题。
C哥喝了口水,淡定的说:“这个嘛,我以前也遇到过。”
“您也遇到过,怎么解决的?”
“这个问题,哈哈,姑且就叫MVC的烦恼吧!MVC将View与Model进行了分离解耦,这当然很好,但不少人就将业务逻辑的处理写在了Controller里,致使Controller愈来愈臃肿,以至最后都没法维护。”
“对对对,您说的太对了,我就常常这样写。”
[图片:臃肿的代码]
C哥继续说道:其实,Controller不该该处理过多的业务逻辑。给你举两个例子就明白了。
控制器,就像遥控器同样。
你见过遥控器关心电视怎么播放视频吗?没有,遥控器只是发送播放视频的信号,具体的播放视频的细节,遥控器不会关心。
控制器,就像将军同样。
你见过将军亲自为每位士兵配备武器吗?细节部分,将军没必要过问,将军的职责是领兵打仗,这叫各司其职,不然就乱了。
说到这里,小二恍然大悟:“听C哥一席话,胜读十年书啊!”
“既然这样,就给Controller减减肥吧。”C哥说到
“是啊,可是怎么减肥呢?”
“我给你讲一种设计模式-外观模式,你就懂了”。
“好啊好啊,洗耳恭听”。
C哥又讲到:
外观模式,提供了统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,使得子系统更加易用。
也就是说,干一件很复杂的事的时候,你想团队中每一个人都花一年半载去学习如何作这件事吗?利用外观模式,我只须要指定一我的去学会这些复杂的步骤,而后我再告诉这个接口人去干就好了。
“若是让你实现上面那个需求,你可能会找到用户提交订单的Controller,而后在Controller里写下面一大堆代码。是否是?”
/****文件名:SubmitController.class.php(用户提交模块controller)****/
//..............接上...2000行代码..............//
//获取用户邮箱
public function get_user_email($uid){
return new User()->get_user_email($uid);
}
//获取要发送给用户的内容
public function get_email_content($uid){
return new Email()->get_email_content($uid);
}
//发送邮件
public function send_email($email,$content){
return new Email()->send_email($email,$content);
}
//用户提交订单触发的方法
public function submit(){
$email=$this->get_user_email($uid);
$content=$this->get_email_content($uid);
$this->send_email($email,$content);
}复制代码
“对对对,我会这么写”。
"其实你用的ThinkPhp,有一层叫Logic层,关于业务逻辑处理的部分,你能够写在Logic层里。这样,Controller层就变得很轻量了,好维护了。"
/****文件名:SendEmailFacadeLogic.class.php(发送邮件Logic)****/
//获取用户邮箱
private function get_user_email($uid){
return new User()->get_user_email($uid);
}
//获取要发送给用户的内容
private function get_email_content($uid){
return new Email()->get_email_content($uid);
}
//发送邮件
public function send_email($uid){
$email=$this->get_user_email($uid);
$content=$this->get_email_content($uid);
return new Email()->send_email($email,$content);
}复制代码
/****文件名:SubmitController.class.php(用户提交模块controller)****/
//..............接上...2000行代码..............//
D('SendEmail','Logic')->send_email($uid);复制代码
“你看,加了Logic层,业务逻辑都放在Logic里面去处理,Controller是否是瘦了不少呢?Logic层为Controller提供了一个高层的接口用来发送邮件,也就是Facade模式的应用。”
“小二,明白些了吧?”
“嗯嗯,明白了好多,犹如醍醐灌顶!”
“为了加深你的理解,我给你画个简单的实例图吧”。
“真的吗?太谢谢C哥了”。
看了C哥画的图,小二小彻小悟了。
“C哥,Facade模式真不错,你看,这样统一成简单的接口后:”
一、下降了系统的耦合度。提交订单的Controller,不再用与UserController、EmailController等耦合了。如今只须要关心SendEmailFacadeLogic就能够了。
二、而且,用户使用了Facade模式后,有了统一的入口,就很容易监控客户对系统的使用了。就如Thinkphp的单一入口同样。
“嗯嗯。小二真聪明,确实是这样。”
更多精彩,请关注公众号“聊聊代码”,让咱们一块儿聊聊“左手代码右手诗”的事儿。