前言

以小说的笔法写的设计模式系列文章,你绝对看得懂![首发于公众号:"聊聊代码"]

设计模式系列·王小二需求历险记(一)
设计模式系列·王小二需求历险记(二)
设计模式系列·封装、继承、多态
设计模式系列·初探设计模式之王小二的疑问
设计模式系列·Facade模式之MVC的烦恼
设计模式系列·Adapter 模式之如何优雅的使用别人的轮子
设计模式系列·类爆炸之Bridge模式
设计模式系列·工厂方法模式之 Code Review
设计模式系列·抽象工厂模式

------华丽的分割线:正文开始------

午后闲谈

公司最近项目不忙,午间小憩之后,小二找到C哥攀谈了起来。

"C哥,忙啥呢?"
"也没忙啥,就是随便看看。"

"哦哦,我最近也不怎么忙。你上次给我讲的工厂模式,受益匪浅啊!"
"哈哈,是嘛!其实你不知道,还有抽象工厂模式呢!"

"抽象工厂模式?愿闻其详。"
"好,反正最近也不忙,就给你讲讲吧。"

从奥迪车说起

"小二,你知道,奥迪A4与A6,他们使用的轮胎与灯泡是不一样的。"
"是,型号不一样,轮胎与灯泡肯定不一样。"

"假设现在需要制造A4与A6的轮胎和灯泡,你会怎么写代码?"
"这个嘛,好写!"

小二熟练的打开电脑,挥斥方遒,迅速的写出了代码。

<?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的灯泡。相互依赖,是为高耦合。

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」即可关注。

关注「聊聊代码」,让我们一起聊聊“左手代码右手诗”的事儿。

设计模式系列·抽象工厂模式相关推荐

  1. 抽象工厂模式_设计模式系列—抽象工厂模式

    前言 23种设计模式速记 单例(singleton)模式 工厂方法(factory method)模式 23种设计模式快速记忆的请看上面第一篇,前面说完了工厂方法模式,我们发现工厂方法模式存在一个严重 ...

  2. C#设计模式(4)——抽象工厂模式

    C#设计模式(4)--抽象工厂模式 一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法 ...

  3. 设计模式三—抽象工厂模式

    设计模式三-抽象工厂模式 一.定义 抽象工厂模式是工厂方法模式的进一步抽象.如果产品簇中只有一种产品,则退化为工厂方法模式. 二.原理图 三.代码实例 * 苹果和土豆是园丁1的杰作 * 葡萄和西红柿是 ...

  4. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Facto ...

  5. 设计模式复习-抽象工厂模式

    设计模式复习-抽象工厂模式 有两种硬件,PC和Phone,有两种系统,Windows和Linux,现在假设PC和Phone上全都能安装这两个系统,并且将来硬件不会在变化,但是系统可能需要扩展,比如扩展 ...

  6. 设计模式之四(抽象工厂模式第三回合)

    原文:设计模式之四(抽象工厂模式第三回合) 前言 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如I ...

  7. python抽象工厂模式_Python设计模式之抽象工厂模式

    Python设计模式之抽象工厂模式 这篇文章主要为大家详细介绍了Python设计模式之抽象工厂模式,感兴趣的小伙伴们可以参考一下 python面向对象编程入门,我们需要不断学习进步 "&qu ...

  8. 设计模式-04抽象工厂模式

    设计模式-04抽象工厂模式 文章中涉及到的代码,请自行下载 https://gitee.com/pan_xiao_lei123/designmode.git 前面介绍的工厂方法模式中考虑的是一类产品的 ...

  9. Java 设计模式之抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...

最新文章

  1. 工作中的一次linux防范ddos***___转载
  2. php mysql特殊符号过滤微信小程序_微信小程序数据过滤(filter)方法
  3. Eclipse juno 中安装 JBoss Tools,集成Hibernate
  4. normalize.css
  5. ALI的Tensorflow炼成与GAN科普
  6. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用
  7. 今天我的MSN提示升级了
  8. Go语言---并发编程goroutine
  9. linux关闭rac某一节点,实现多次不完全恢复(RAC环境需要将另一节点关闭)
  10. Web页面输出Excel的数字问题解决方法
  11. Chrome 中迅雷的插件(正确的下载地址)下载以及安装(一)
  12. 用java编写某年某月的日历_Java-查询某年某月一个月的数据,以日历的形式展示。...
  13. 修改程序的图标与详细描述
  14. ubuntu安装原生迅雷,让下载成为简单
  15. android 股票行情走势图K线控件 KLineView
  16. UE4 Pak包热更新
  17. Arduino 用4位共阴数码管造一个计数器
  18. 有关魅族手机遇到TextView显示异常
  19. poll?transport=longpollconnection...烦人的请求
  20. 网络安全基本属性和STRIDE

热门文章

  1. 用.NET创建Windows服务
  2. php几个预定义变量$_SERVER['DOCUMENT_ROOT']
  3. 自己写的内存池Slabs
  4. mysql邮箱配置文件_SQL-数据库邮箱配置
  5. oracle比较运算符 速度,Oracle学习日志-5(算数运算符,比较运算符和逻辑运算符)...
  6. python好不好用_python应用情况怎么样?是否真的值得学习?
  7. 电脑画画软件_手绘、板绘、还有用pad画画都有啥区别?
  8. 保存数组_面试官:讲一讲你对据结构——数组、链表、栈、队列的理解
  9. Java学习总结:45(字符编码)
  10. linux mv 环境变量,linux环境变量,cp,mv命令,more,less,cat,tail,head,的使用...