PHP设计模式(一)工厂模式Factory实例详解【创建型】

本文实例讲述了PHP设计模式(一)工厂模式Factory。分享给大家供大家参考,具体如下:

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。

模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?

解决方案:建立一个工厂来创建对象。

实现:

一、引言

1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。
    2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。
    3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。你需要指定某个具体的工厂才能生产车出来。
    4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。而且这空调必须对应给系列车才能使用。于是这个工厂开始生产宝马车和需要的空调。
         最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.
   (我只是举个例子,说到宝马配置空调完全是为了举例,甚至有点扯,哪有车和空调必须对应才能使用啊)
     这就是工厂模式。

二、分类

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 
工厂模式可以分为三类: 
1)简单工厂模式(Simple Factory) 
2)工厂方法模式(Factory Method) 
3)抽象工厂模式(Abstract Factory) 
         这三种模式从上到下逐步抽象,并且更具一般性。 
        GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

三、区别

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。

区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
两者皆可。

四、简单工厂模式

建立一个工厂(一个函数或一个类方法)来制造新的对象。

分布说明引子:从无到有。客户自己创建宝马车,然后拿来用。

<?php
/**
 * 车子系列
 *
 */
Class BWM320{
function __construct($pa) {

}
}
Class BMW523{
  function __construc($pb){
}
}
/**
 *
 * 客户自己创建宝马车
 */
class Customer {

  function createBMW320(){
    return new BWM320();
  }

  function createBMW523(){
    return new BMW523();
  }
}

客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车型号就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式

即我们建立一个工厂类方法来制造新的对象。如图:

产品类:

<?php
/**
 * 车子系列
 *
 */
abstract Class BWM{
  function __construct($pa) {

  }
}
Class BWM320 extends BWM{
  function __construct($pa) {

  }
}
Class BMW523 extends BWM{
  function __construc($pb){

  }
}

工厂类:

/**
 *
 * 工厂创建车
 */
class Factory {
  static function createBMW($type){
    switch ($type) {
     case 320:
       return new BWM320();
     case 523:
       return new BMW523();
    //....
  }
}

客户类:

/**
 *
 * 客户通过工厂获取车
 */
class Customer {
  private $BMW;
  function getBMW($type){
    $this¬-> BMW = Factory::createBMW($type);
  }
}

简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。

先来看看它的组成: 
         1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
         2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。         
         3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW($type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类 或者上帝类。 
        我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员:( 
        于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。

五、工厂方法模式

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 
工厂方法模式组成:

1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 
       2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 
       3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 
       4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 
       工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!

代码如下:

产品类:

<?php
/**
 * 车子系列
 *
 */
abstract Class BWM{
function __construct($pa) {
}
}
Class BWM320 extends BWM{
function __construct($pa) {
}
}
Class BMW523 extends BWM{
  function __construc($pb){
}
}

创建工厂类:

/**
 * 创建工厂的接口
 *
 */
interface FactoryBMW {
    function createBMW();
}
/**
 *
 * 创建BWM320车
 */
class FactoryBWM320 implements FactoryBMW {
  function createBMW($type){
   return new BWM320();
  }
}
/**
 *
 * 创建BWM523车
 */
class FactoryBWM523 implements FactoryBMW {
  function createBMW($type){
   return new BMW523();
  }
}

客户类:

/**
 *
 * 客户得到车
 */
class Customer {
  private $BMW;
  function getBMW($type){
   switch ($type) {
    case 320:
      $BWM320 = new FactoryBWM320();
      return $BWM320->createBMW();
    case 523:
      $BWM523 = new FactoryBWM523();
      return $BWM320->createBMW();
      //....
   }

 }
}

可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情 况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实 现。

工厂方法小结:

工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式:

1)当客户程序不需要知道要使用对象的创建过程。 
     2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判 断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。
       面对这种情况,我们可以使用反射机制:

 class Customer {
   private $BMW;
   function getBMW($type){
     $class = new ReflectionClass('FactoryBWM' .$type );//建立 'FactoryBWM'这个类的反射类
     $instance = $class->newInstanceArgs();//相当于实例化'FactoryBWM' .$type类
     return $instance->createBMW();
    //或者直接
     /**
     * $instance = new 'FactoryBWM' .$type();
     * return $instance->createBMW();
     */
  }
}

六、抽象工厂模式

随着客户的要求越来越高,宝马车需要配置空调。于是这个工厂开始生产宝马车和配置需要的空调。这时候工厂有二个系列的产品:宝马车和空调.宝马车必须使用对应的空调才能使用.这时候分别使用一个车工厂和一个空调工厂都不能满足我们的需求,我们必须确认车跟空调的对应关系。因此把车工厂跟空调工厂联系在一起。因此出现了抽象工厂模式。

可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。

抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件:

1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
     2)同属于同一个产品族的产品以其使用。

抽象工厂模式的各个角色(和工厂方法一样):

1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 
     2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
     3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。
     4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。

其结构:

我们的例子:

代码:

产品类:

<?php
/**
 * 车子系列以及型号
 *
 */
abstract class BWM{
}
class BWM523 extends BWM {
}
class BWM320 extends BWM {
}
/**
 * 空调
 *
 */
abstract class aircondition{
}
class airconditionBWM320 extends aircondition {
}
class airconditionBWM52 extends aircondition {
}

创建工厂类:

/**
 * 创建工厂的接口
 *
 */
interface FactoryBMW {
   function createBMW();
   function createAirC();
}
/**
 *
 * 创建BWM320车
 */
class FactoryBWM320 implements FactoryBMW {
  function createBMW(){
  return new BWM320();
}
function createAirC(){ //空调
  return new airconditionBWM320();
}
}
/**
 *
 * 创建BWM523车
 */
class FactoryBWM523 implements FactoryBMW {
  function createBMW(){
  return new BWM523();
}
function createAirC(){
  return new airconditionBWM523();
}
}

客户:

/**
 *
 * 客户得到车
 */
class Customer {
  private $BMW;
  private $airC;
  function getBMW($type){
    $class = new ReflectionClass('FactoryBWM' .$type );//建立 Person这个类的反射类
    $instance = $class->newInstanceArgs();//相当于实例化Person 类
    $this->BMW = $instance->createBMW();
    $this->airC = $instance->createAirC();
  }
}

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

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

(0)

相关推荐

  • PHP设计模式概论【概念、分类、原则等】

    本文实例讲述了PHP设计模式.分享给大家供大家参考,具体如下: 1. 设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样. 模式的经典定义:每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心,通过这种方

  • PHP设计模式之适配器模式代码实例

    目标: 可将一个类的接口转换成客户希望的另外一个接口,使得原本不兼容的接口能够一起工作.通俗的理解就是将不同接口适配成统一的API接口. 角色: Target适配目标,该角色定义把其他类转换为何种接口,也就是我们的期望接口. Adaptee被适配者,就是需要被适配的接口. Adapter适配器,其他的两个角色都是已经存在的角色,而适配器角色是需要新建立的,它用来对Adaptee与Target接口进行适配. 应用场景: 如数据操作有mysql.mysqli.pdo.sqlite.postgresq

  • php设计模式之适配器模式实例分析【星际争霸游戏案例】

    本文实例讲述了php设计模式之适配器模式.分享给大家供大家参考,具体如下: 星际的很多兵种,都有至少一项特殊技能.而且有些兵种的技能是相同的,比如虫族部队都会恢复血. 如果按照一般的思路,把技能的操作和控制作为方法,放在每个兵种的定义类来实现,代码会重复,也不容易修改. 那我们就会考虑用继承的办法,比如我们可以设计一个虫族的基类,里面有受伤后血恢复的方法. 在设计刺蛇(Hydralisk,口水兵)的时候,我们可以让刺蛇类继承虫族基类. 但是刺蛇是可以研发钻地的,而钻地不是刺蛇独有的功能,是虫族地

  • PHP设计模式之适配器模式定义与用法详解

    本文实例讲述了PHP设计模式之适配器模式定义与用法.分享给大家供大家参考,具体如下: 适配器很容易理解, 大多数人家庭都有手机转接器, 用来为移动电话充电,这就是一种适配器. 如果只有USB接头, 就无法将移动电话插到标准插座上. 实际上, 必须使用一个适配器, 一端接USB插头, 一端接插座. 当然, 你可以拿出电气工具,改装USB连接头, 或者重新安装插座, 不过这样会带来很多额外的工作, 而且可能会把连接头或插座弄坏. 所以, 最可取的方法就是找一个适配器. 软件开发也是如此. 类适配器模

  • PHP设计模式之适配器模式(Adapter)原理与用法详解

    本文实例讲述了PHP设计模式之适配器模式(Adapter)原理与用法.分享给大家供大家参考,具体如下: 这个适配器模式,就是为了将一个类的接口转换成客户希望的另外一个接口,并且使用原本不兼容的而不能在一起工作的那些类可以在一起工作.它的核心思想就是把对某些相似的类的操作转化为一个统一的"接口"(这里是比喻的说话)--适配器,或者比喻为一个"界面",统一或屏蔽了那些类的细节.适配器模式还构造了一种"机制",使"适配"的类可以很容

  • PHP设计模式(三)建造者模式Builder实例详解【创建型】

    本文实例讲述了PHP设计模式:建造者模式Builder.分享给大家供大家参考,具体如下: 1. 概述 在软件开发的过程中,当遇到一个"复杂的对象"的创建工作,该对象由一定各个部分的子对象用一定的算法构成,由于需求的变化,复杂对象的各个部分经常面临剧烈的变化,但将它们组合在一起的算法相对稳定. 例子1:买肯德基 典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡.炸鸡.可乐和玩具车).这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的. 客户端:顾客,想去买一

  • PHP设计模式(四)原型模式Prototype实例详解【创建型】

    本文实例讲述了PHP设计模式:原型模式Prototype.分享给大家供大家参考,具体如下: 1.   概述 我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象而不需要提供专门的new()操作就可以快速完成对象的创建,这无疑是一种非常有效的方式,快速的创建一个新的对象. 例子1:孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递 下面是一个邮寄快递的场景: "给我寄个快递."顾客说. &qu

  • php设计模式之适配器模式原理、用法及注意事项详解

    本文实例讲述了php设计模式之适配器模式原理.用法及注意事项.分享给大家供大家参考,具体如下: 在这个有没有对象都要高呼"面向对象"的年代,掌握面向对象会给我们带来意想不到的方便.学编程的小伙伴从开始能写几行代码实现简单功能到后来懂得将一些重复的操作组合起来形成一个"函数",再到后来将"函数"和属性组合起来形成一个"类".一步步走来,我们在考虑着机器运行代码效率的提高的同时也在考虑减轻程序员的工作量. 那么我们今天讲到的适配器

  • 学习php设计模式 php实现适配器模式

    一.意图 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原来由于接口不兼容而不能一起工作的那此类可以一起工作 二.适配器模式结构图 三.适配器模式中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所期待得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:对Adaptee的接口与Target接口进行适配:适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 四.适配器模式适用场景 1.你想使用一

  • PHP设计模式之适配器模式原理与用法分析

    本文实例讲述了PHP设计模式之适配器模式原理与用法.分享给大家供大家参考,具体如下: 一.什么是适配器模式 适配器模式有两种:类适配器模式和对象适配器模式.其中类适配器模式使用继承方式,而对象适配器模式使用组合方式.由于类适配器模式包含双重继承,而PHP并不支持双重继承,所以一般都采取结合继承和实现的方式来模拟双重继承,即继承一个类,同时实现一个接口.类适配器模式很简单,但是与对象适配器模式相比,类适配器模式的灵活性稍弱.采用类适配器模式时,适配器继承被适配者并实现一个接口:采用对象适配器模式时

  • php设计模式 Adapter(适配器模式)

    复制代码 代码如下: <?php /** * 适配器模式 * * 将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作 */ // 这个是原有的类型 class OldCache { public function __construct() { echo "OldCache construct<br/>"; } public function store($key,$value) { echo "OldCach

  • PHP设计模式(五)适配器模式Adapter实例详解【结构型】

    本文实例讲述了PHP设计模式:适配器模式Adapter.分享给大家供大家参考,具体如下: 1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库的发展和进化. 例子1:iphone4,你即可以使用UBS接口连接电脑来充电,假如只有iphone没有电脑,怎么办呢?苹果提供了iphone电源适配器.可以使用这个电源适配器充电.这个iphone的电源适配器就是类似我们说的适配器模式.(电源适配器就是把电源变

随机推荐