公司最近项目不忙,午间小憩以后,小二找到C哥攀谈了起来。php
"C哥,忙啥呢?"
"也没忙啥,就是随便看看。"设计模式
"哦哦,我最近也不怎么忙。你上次给我讲的工厂模式,受益不浅啊!"
"哈哈,是嘛!其实你不知道,还有抽象工厂模式呢!"函数
"抽象工厂模式?愿闻其详。"
"好,反正最近也不忙,就给你讲讲吧。"spa
"小二,你知道,奥迪A4与A6,他们使用的轮胎与灯泡是不同的。"
"是,型号不同,轮胎与灯泡确定不同。"设计
"假设如今须要制造A4与A6的轮胎和灯泡,你会怎么写代码?"
"这个嘛,好写!"code
小二熟练的打开电脑,挥斥方遒,迅速的写出了代码。对象
<?php class Client{ //根据不一样型号生产不一样轮胎 public function produce_wheel($type){ switch ($type){ case 'A4': $obj=new AudiA4Wheel(); break; case 'A6': $obj=new AudiA6Wheel(); break; default: throw new Exception('no instance found'); } $obj->produce_wheel(); } //根据不一样型号生产不一样灯泡 public function produce_light($type){ switch ($type){ case 'A4': $obj=new AudiA4Light(); break; case 'A6': $obj=new AudiA6Light(); break; default: throw new Exception('no instance found'); } $obj->produce_light(); } } $client=new Client(); $client->produce_wheel('A4'); $client->produce_light('A4');
"C哥,大致就是这么个思路。您看看对吗?"
"嗯,这代码确实也实现了功能,可是,有问题。"接口
"有问题?什么问题?"
"你这代码存在着低内聚、高耦合的问题,很差维护啊。"图片
"怎么低内聚、高耦合了?"小二一脸茫然。
C哥镇定自若的解释道:
好比,如今我要增长奥迪的型号A8,那你代码里的函数produce_wheel()
与produce_light()
是否是都要改?也就是这两个函数是相互依赖的,不可能用A6的轮子,而用A8的灯泡。相互依赖,是为高耦合。rem
produce_wheel()
与 produce_light()
函数,这两个函数都关心本身须要什么型号的产品,而且都负责把相应的产品生产出来。也就是,他有两个职责:关心型号、根据不一样型号生产出对应的产品。但这两个职责是毫无关联的,没有半毛钱的关系。职责过多且分散,是为低内聚。
"C哥这么一说,还真是这么回事。"
"哈哈,低内聚高耦合的代码也能实现需求,可是这样的代码很差维护。"
"嗯嗯,C哥,有啥好办法吗?"
"固然有了,咱们这里就用到了抽象工厂模式。"
"根据我多年的经验,出现switch语句的地方,每每意味着须要抽象、或者存在着放错责任的地方。"
"宝贵的经验,记下了!"
"小二,其实这里,就是放错了责任。"
"嗯,怎么说呢?"
"Client端既关心如何建立对象,又关心如何用对象来制造轮子、灯泡。"
"是,他的责任太多了。"
"其实,Client端只负责使用对象制造相关产品就好了。他不用负责创造对象。创造对象,交给Client端来作,就是放错了责任。"
"对,确实是这样。"
"还记得前几天给你讲的工厂模式吗?工厂模式也是为了解决这个问题。"
"记得记得,工厂模式也是为了实现责任的分离。"
"工厂模式针对一种产品提供一个工厂类,而抽象工厂模式是针对一组相关或相互依赖的产品提供一个工厂类。"
"那抽象工厂模式就是工厂模式的升级版本啦!"
"是的。在这里,Client端负责向Factory发出请求,Factory返回相关对象,Client端再根据Factory返回的对象,制造相关的产品。"
"也就是Client负责使用对象,Factory负责建立对象!"
"是的,小二很聪明嘛!看看抽象工厂模式的类图吧!"
"好的,C哥。"
"小二啊,跟你讲了这么多,接下来就看你了!"
"好的C哥,我立刻画出类图、写出代码。"
小二仿照着C哥的类图,又画出了用抽象工厂解决上面问题的类图。
画好类图,代码也就好写了!
<?php //灯泡产品接口 interface Light{ public function produce_light(); } //奥迪A4灯泡产品 class AudiA4Light implements Light{ public function produce_light() { echo "AudiA4 Light produced!\n"; } } //奥迪A6灯泡产品 class AudiA6Light implements Light{ public function produce_light() { echo "AudiA6 Light produced!\n"; } } //轮子产品接口 interface Wheel{ public function produce_wheel(); } //奥迪A4轮子 class AudiA4Wheel implements Wheel { public function produce_wheel() { echo "AudiA4 Wheel produced!\n"; } } //奥迪A6轮子 class AudiA6Wheel implements Wheel { public function produce_wheel() { echo "AudiA6 Wheel produced!\n"; } } //工厂接口 interface Factory{ public function CreateWheel(); public function CreateLight(); } //奥迪A4工厂 class A4Factory implements Factory { public function CreateWheel() { return new AudiA4Wheel(); } public function CreateLight() { return new AudiA4Light(); } } //奥迪A6工厂 class A6Factory implements Factory { public function CreateWheel() { return new AudiA6Wheel(); } public function CreateLight() { return new AudiA6Light(); } } //客户端调用类 class Client{ //运行主函数 public static function main($type){ $reflection=new ReflectionClass($type.'Factory'); $factory=$reflection->newInstance(); self::run($factory); } //生产产品 public static function run(Factory $factory){ $wheel=$factory->CreateWheel(); $wheel->produce_wheel(); $light=$factory->CreateLight(); $light->produce_light(); } } Client::main('A6');
"嗯嗯,小二不错嘛。简单工厂、工厂方法、抽象工厂模式,你都掌握了。"
"哈哈,感谢C哥的教导!"
"恭喜你在设计模式打怪升级的道路上,再次斩获新技能!"
听到这句话,小二内心美滋滋的,嘴角露出了得意的微笑......
转载声明:本文首发于自公众号「聊聊代码」,搜索「talkpoem」便可关注。
关注「聊聊代码」,让咱们一块儿聊聊“左手代码右手诗”的事儿。