经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
PHP设计模式之工厂方法模式
来源:cnblogs  作者:ZyBlog  时间:2020/12/14 17:27:57  对本文有异议

上回说到,简单工厂不属于GoF的二十三种设计模式,这回可就来真家伙了,大名顶顶的工厂方法模式前来报道!

GoF类图解释

工厂方法模式对比简单工厂来说,最核心的一点,其实就是将实现推迟到子类。怎么理解呢?我们可以将上回的简单工厂当做父类,然后有一堆子类去继承它。createProduct()这个方法在父类中也变成一个抽象方法。然后所有的子类去实现这个方法,不再需要用switch去判断,子类直接返回一个实例化的对象即可。

GoF定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化推迟到其子类。

GoF类图

工厂方法结构类图

  • 类图中的Product为产品
  • 类图中的Creator为创建者
  • 创建者父类有一个抽象的FactoryMethod()工厂方法
  • 所有创建者子类需要实现这个工厂方法,返回对应的具体产品
  • 创建者父类可以有一个AnOperation()操作方法,直接返回product,可以使用FactoryMethod()去返回,这样外部只需要统一调用AnOperation()

代码实现

首先是商品相关的接口和实现类,和简单工厂的类似:

  1. // 商品接口
  2. interface Product{
  3. function show() : void;
  4. }
  5. // 商品实现类A
  6. class ConcreteProductA implements Product{
  7. public function show() : void{
  8. echo "I'm A.\n";
  9. }
  10. }

接下来是创建者的抽象和实现类:

  1. // 创建者抽象类
  2. abstract class Creator{
  3. // 抽象工厂方法
  4. abstract protected function FactoryMethod() : Product;
  5. // 操作方法
  6. public function AnOperation() : Product{
  7. return $this->FactoryMethod();
  8. }
  9. }
  10. // 创建者实现类A
  11. class ConcreteCreatorA extends Creator{
  12. // 实现操作方法
  13. protected function FactoryMethod() : Product{
  14. return new ConcreteProductA();
  15. }
  16. }

这里和简单工厂就有了本质的区别,我们去掉了恶心的switch,让每个具体的实现类来进行商品对象的创建。没错,单一和封闭,每个单独的创建者子类只在工厂方法中和一个商品有耦合,有没有其他商品和其他的工厂来跟客户合作过这个子类完全不知道。

同样还是拿手机来比喻:我是一个卖手机的批发商(客户Client,业务方),我需要一批手机(产品ProductA),于是我去让富X康(工厂Creator)来帮我生产。我跟富士康说明了需求,富士康说好的,让我的衡阳工厂(ConcreteCreatorA)来搞定,不需要总厂上,你这小单子,洒洒水啦。然后过了一阵我又需要另一种型号的手机(产品ProductB),富士康看了看后又让郑州富士康(ConcreteCreatorB)来帮我生产。反正不管怎么样,他们总是给了我对应的手机。而且郑州工厂并不知道衡阳工厂生产过什么或者有没有跟我合作过,这一切只有我和总工厂知道。

完整代码:工厂方法模式

实例

场景:光说不练假把式,把上回的短信发送改造改造,我们依然还是使用上回的那几个短信发送商。毕竟大家已经很熟悉了嘛,不过以后要更换也说不定,商场如战场,大家还是利益为先。这样的话,我们通过工厂方法模式来进行解耦,就可以方便的添加修改短信提供商咯。

短信发送类图

短信发送工厂方法

代码实现

  1. <?php
  2. interface Message {
  3. public function send(string $msg);
  4. }
  5. class AliYunMessage implements Message{
  6. public function send(string $msg){
  7. // 调用接口,发送短信
  8. // xxxxx
  9. return '阿里云短信(原阿里大鱼)发送成功!短信内容:' . $msg;
  10. }
  11. }
  12. class BaiduYunMessage implements Message{
  13. public function send(string $msg){
  14. // 调用接口,发送短信
  15. // xxxxx
  16. return '百度SMS短信发送成功!短信内容:' . $msg;
  17. }
  18. }
  19. class JiguangMessage implements Message{
  20. public function send(string $msg){
  21. // 调用接口,发送短信
  22. // xxxxx
  23. return '极光短信发送成功!短信内容:' . $msg;
  24. }
  25. }
  26. abstract class MessageFactory{
  27. abstract protected function factoryMethod();
  28. public function getMessage(){
  29. return $this->factoryMethod();
  30. }
  31. }
  32. class AliYunFactory extends MessageFactory{
  33. protected function factoryMethod(){
  34. return new AliYunMessage();
  35. }
  36. }
  37. class BaiduYunFactory extends MessageFactory{
  38. protected function factoryMethod(){
  39. return new BaiduYunMessage();
  40. }
  41. }
  42. class JiguangFactory extends MessageFactory{
  43. protected function factoryMethod(){
  44. return new JiguangMessage();
  45. }
  46. }
  47. // 当前业务需要使用百度云
  48. $factory = new BaiduYunFactory();
  49. $message = $factory->getMessage();
  50. echo $message->send('您有新的短消息,请查收');

完整源码:短信发送工厂方法

说明

  • 和类图完全一致,基本不需要什么说明了吧,注意工厂方法模式的特点,实现推迟到了子类!!
  • 业务调用的时候需要耦合一个Factory子类。确实是这样,如果你想一个统一的出口来调用,请在外面加一层简单工厂就好啦,这就当成一道思考题吧
  • 不拘泥于目前的形式,可以不用抽象类,直接用一个接口来定义工厂方法,摒弃掉getMessage()方法,外部直接调用公开的模板方法(factoryMethod)即可

下期看点

抽象工厂模式,老大哥即将登场。压轴的总是最强悍的,让我们看看老大哥的本事!

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

原文链接:http://www.cnblogs.com/zyblog-coder/p/14118895.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号