PHP设计模式之简单工厂和工厂模式实例分析


Posted in PHP onMarch 25, 2019

本文实例讲述了PHP设计模式之简单工厂和工厂模式。分享给大家供大家参考,具体如下:

工厂模式是创建型模式的一种,分为简单工厂模式,工厂模式,抽象工厂模式,简单工厂可以称之为工厂模式的一个特例

先用一段简单的代码说明一下,现在假设我们是顾客,需要苹果味饮料和香蕉味饮料

<?php
class AppleDrink{
  function getDrinkName()
  {
    echo '苹果饮料';
  }
}
class BananaDrink{
  function getDrinkName()
  {
    echo '香蕉饮料';
  }
}
//顾客1
$apple = new AppleDrink();
$apple->getDrinkName();
echo "<br/>";
$banana = new BananaDrink();
$banana->getDrinkName();
echo "<br/>";
//顾客2
$apple1 = new AppleDrink();
$apple1->getDrinkName();
echo "<br/>";
$banana1 = new BananaDrink();
$banana1->getDrinkName();

运行结果:

苹果饮料
香蕉饮料
苹果饮料
香蕉饮料

这是最基本的写法,顾客和饮料是强耦合关系,也就是咱们平常说的硬编码

有一天,老板觉得AppleDrink这个名字在国内不好卖,想要改成Xingmu(醒目)这种接中国地气的名字(麦当劳改成金拱门)

你会发现,需要去代码中找到每一处NEW的地方,全部改成new Xingmu()

如果它还有其他的初始化步骤,就更是噩梦,很可能会引起一些不必要的麻烦

下面咱们用简单工厂模式,更改一下这个文件

<?php
class AppleDrink{
  function getDrinkName()
  {
    echo '苹果饮料';
  }
}
class BananaDrink{
  function getDrinkName()
  {
    echo '香蕉饮料';
  }
}
class FruitFactory{
  function makeDrink($fruit){
    if ($fruit == 'apple'){
      return new AppleDrink();
    }elseif ($fruit == 'banana'){
      return new BananaDrink();
    }
  }
}
$factory = new FruitFactory();
$apple = $factory->makeDrink('apple');
$apple->getDrinkName();
echo "<br/>";
$banana = $factory->makeDrink('banana');
$banana->getDrinkName();
echo "<br/>";
$apple1 = $factory->makeDrink('apple');
$apple1->getDrinkName();
echo "<br/>";
$banana1 = $factory->makeDrink('banana');
$banana1->getDrinkName();

运行结果:

苹果饮料
香蕉饮料
苹果饮料
香蕉饮料

现在我们发现,假如说老板想改名字,我只需要把FruitFactory里的new AppleDrink改为new Xingmu()即可,其他地方都不需要改动,也不用翻代码找哪些地方用new了,实现了顾客和饮料之间的解耦,也符合面向对象的设计思想,我只是想要一瓶饮料,我并不需要了解这个饮料是怎么制造出来的

这就是简单工厂模式,用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的,外界与具体类隔离开来,耦合性低,有利于整个软件体系结构的优化,适用于工厂类负责创建的对象比较少,客户只知道传入了工厂类的参数,对于如何创建对象(逻辑)不关心,简单工厂模式又叫静态工厂模式 可以把工厂类的方法写成静态方法 在不需要实例化工厂的前提下 直接调用静态方法 返回所需实例

好的,那么接下来,问题又来了,公司准备多元化产品,增加桔子味饮料,那么我们需要怎么做呢,首先要增加桔子味饮料类,然后需要在工厂里增加判断,当水果标识是orange的时候,返回桔子味饮料

class OrangeDrink{
  function getDrinkName()
  {
    echo '桔子味饮料';
  }
}
class FruitFactory{
  function makeDrink($fruit){
    if ($fruit == 'apple'){
      return new AppleDrink();
    }elseif ($fruit == 'banana'){
      return new BananaDrink();
    }elseif ($fruit == 'orange'){
      return new OrangeDrink();
    }
  }
}

然后当以后每次需要增加新的产品时,我们都需要更改工厂文件,当对象生成复杂的时候,这个工厂文件会越来越大,更改或许会引起一些意想不到的问题

面向对象的设计原则,对扩展开放,对更改关闭,那么有没有办法,在不更改原有代码的基础上,增加产品呢

答案是有的,咱们再改写一下这个方法

<?php
interface Drink{
  function getDrinkName();
}
class AppleDrink implements Drink{
  function getDrinkName()
  {
    echo '苹果味饮料';
  }
}
class BananaDrink implements Drink{
  function getDrinkName()
  {
    echo '香蕉味饮料';
  }
}
interface FruitFactory{
  function makeDrink();
}
class AppleFactory implements FruitFactory{
  function makeDrink()
  {
    return new AppleDrink();
  }
}
class BananaFactory implements FruitFactory{
  function makeDrink()
  {
    return new BananaDrink();
  }
}
$appleFactory = new AppleFactory();
$apple = $appleFactory->makeDrink();
$apple->getDrinkName();
echo "<br/>";
$bananaFactory = new BananaFactory();
$banana = $bananaFactory->makeDrink();
$banana->getDrinkName();

运行结果:

苹果味饮料
香蕉味饮料

现在当再次需要增加桔子味饮料时,只需要增加桔子味饮料产品和桔子味饮料工厂即可,不需要改动原来的代码

class OrangeDrink implements Drink{
  function getDrinkName()
  {
    echo '桔子味饮料';
  }
}
class OrangeFactory implements FruitFactory{
  function makeDrink()
  {
    return new OrangeDrink();
  }
}

这就是工厂模式,它是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现开闭原则,实现了对扩展开放,对更改关闭。其次实现更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式是对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

 总结:

无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
用PHP读注册表
Oct 09 PHP
桌面中心(一)创建数据库
Oct 09 PHP
PHP删除HTMl标签的实现代码
Jun 30 PHP
php读取mysql中文数据出现乱码的解决方法
Aug 16 PHP
smarty中英文多编码字符截取乱码问题解决方法
Oct 28 PHP
php简单分页类实现方法
Feb 26 PHP
PHP设置进度条的方法
Jul 08 PHP
php实现的递归提成方案实例
Nov 14 PHP
Yii2选项卡的简单使用
May 26 PHP
php实现微信分享朋友链接功能
Feb 18 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
Feb 29 PHP
PHP 出现 http500 错误的解决方法
Mar 09 PHP
PHP实现无限极分类的两种方式示例【递归和引用方式】
Mar 25 #PHP
详解PHP神奇又有用的Trait
Mar 25 #PHP
PHP自动载入类文件函数__autoload的使用方法
Mar 25 #PHP
PHP生成短网址的思路以及实现方法的详解
Mar 25 #PHP
PHP错误提示It is not safe to rely on the system……的解决方法
Mar 25 #PHP
mongodb和php的用法详解
Mar 25 #PHP
PHP随机数函数rand()与mt_rand()的讲解
Mar 25 #PHP
You might like
PHP中鲜为人知的10个函数
2014/02/28 PHP
Yii列表定义与使用分页方法小结(3种方法)
2016/07/15 PHP
php中类和对象:静态属性、静态方法
2017/04/09 PHP
基于json的jquery地区联动效果代码
2011/07/06 Javascript
JavaScript高级程序设计 客户端存储学习笔记
2011/09/10 Javascript
Mac/Windows下如何安装Node.js
2013/11/22 Javascript
node.js中的emitter.emit方法使用说明
2014/12/10 Javascript
学习使用Bootstrap输入框、导航、分页等常用组件
2017/05/11 Javascript
详解webpack+vue-cli项目打包技巧
2017/06/17 Javascript
vue购物车插件编写代码
2017/11/27 Javascript
pm2启动ssr失败的解决方法
2019/06/29 Javascript
Vue代码整洁之去重方法整理
2019/08/06 Javascript
vue在响应头response中获取自定义headers操作
2020/07/24 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
2020/08/12 Javascript
vue前端和Django后端如何查询一定时间段内的数据
2021/02/28 Vue.js
[01:02:04]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
10款最好的Web开发的 Python 框架
2015/03/18 Python
Linux中安装Python的交互式解释器IPython的教程
2016/06/13 Python
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
Python按钮的响应事件详解
2019/03/04 Python
anaconda如何查看并管理python环境
2019/07/05 Python
python3获取文件中url内容并下载代码实例
2019/12/27 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
用Python进行websocket接口测试
2020/10/16 Python
matplotlib对象拾取事件处理的实现
2021/01/14 Python
英国旅游额外服务市场领导者:Holiday Extras(机场停车场、酒店、接送等)
2017/10/07 全球购物
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
公司接待方案
2014/03/08 职场文书
预备党员承诺书
2014/03/25 职场文书
购房协议书
2014/04/11 职场文书
教师见习期自我鉴定
2014/04/28 职场文书
期中考试反思800字
2014/05/01 职场文书
高中课程设置方案
2014/05/28 职场文书
党员教师自我剖析材料
2014/09/29 职场文书
2015年业务员工作总结范文
2015/04/07 职场文书
Vue监视数据的原理详解
2022/02/24 Vue.js