详解PHP设计模式之工厂模式

917 阅读2分钟

工厂模式,工厂方法或者类生成对象,而不是在代码中直接new。  

使用工厂模式,可以避免当改变某个类的名字或者方法之后,在调用这个类的所有的代码中都修改它的名字或者参数。

一、什么是工厂模式?

一个类通过本身的静态方法来,实例化一个类并返回一个实例对象; 

二、工厂模式特点?

 类命名特点:nameFactory  eg:  class mysqlFactory{}  【这是为了规范,当然也去起其他任意名字】

 静态方法名称:static public function  factory($class_name){} 【静态方法是类与外界的接口, 返回的是一个对象】

三、优点?

 如果已经使用的类内部发生改变,哪不需要在所有的地方都改变,只需要在类工厂类里改变既可,比如:连接数据库,可以使用mysql 、mysqli、pdo,根据不同参数配置使用不同的数据库操作类 。

四、应用场景

做支付接口的时候,未来可能对应不同的支付网关:支付宝、财付通、网银在线等。方便未来扩展,设计成工厂模式。定一个专门生产网关接口的工厂,抽象出来,做成接口形式,让所有的子类都要实现它的接口。

以后加一个支付方式,要使用哪一种支付方式,改变一下参数即可。

在为用户注册的时候,分为很多种角色的用户。

比如册用户,匿名用户、管理员用户等。完全使用可以使用工厂的思想来实现,代码也容易维护,为每种角色可以生成操作的类等等。

系统对接多个不同类型的数据库,mysql,oracle,sqlserver

五、实例代码

简单工厂模式

定义

又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

角色
  • Factory类:负责创建具体产品的实例
  • Product类:抽象产品类,定义产品子类的公共接口
  • ConcreteProduct 类:具体产品类,实现Product父类的接口功能,也可添加自定义的功能
mydb.php
<?php
interface  mydb{
 
    public function connect();
}

mysqli2.php
<?php 
class mysqli2  implements mydb{
 
    public  function connect(){
        echo 'mysqli';
    }
}

pdo2.php
<?php
class pdo2 implements mydb{
 
    public function connect(){
        echo 'pdo';
    }
}


dbFactory.php
<?php
class dbFactory{ 
 		/*
      * 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字
      * 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
      * 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
      */
    static public function factory($class_name){
        return new $class_name();
    }
 
}

// 实例调用
$obj = dbFactory::factory('pdo2');
$obj->connect()
  
  
获取验证码简单工厂模式
Sms.php
<?php
interface  Sms{ 
    public function send();
}

AliSms.php
<?php 
class AliSms  implements Sms{ 
    public  function send(){}
}

JdSms.php
<?php
class JdSms implements Sms{ 
    public function send(){}
}


SmsFactory.php
<?php
class SmsFactory{ 
 		/*
      * 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字
      * 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
      * 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
      */
    static public function send($class_name){
        return new $class_name();
    }
 
}

// 实例调用
$obj = smsFactory::send('ali');
$obj->send()

工厂方法模式

定义

此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。这样做的好处是核心类只关注工厂类的接口定义,而具体的产品实例交给具体的工厂子类去创建。当系统需要新增一个产品时,无需修改现有系统代码,只需要添加一个具体产品类和其对应的工厂子类,是系统的扩展性变得很好,符合面向对象编程的开闭原则。

角色
  • Product:抽象产品类
  • ConcreteProduct:具体产品类
  • Factory:抽象工厂类
  • ConcreteFactory:具体工厂类
<?php 
interface Animal{
  public function run();
  public function say();
}
class Cat implements Animal
{
  public function run(){
      echo "I ran slowly <br>";
  }
  public function say(){
      echo "I am Cat class <br>";
  }
}
class Dog implements Animal
{
  public function run(){
      echo "I'm running fast <br>";
  }
  public function say(){
      echo "I am Dog class <br>";
  }
}


abstract class Factory{
  abstract static function createAnimal();
}


class CatFactory extends Factory
{
  public static function createAnimal()
  {
      return new Cat();
  }
}
class DogFactory extends Factory
{
  public static function createAnimal()
  {
      return new Dog();
  }
}

$cat = CatFactory::createAnimal();
$cat->say();
$cat->run();

$dog = DogFactory::createAnimal();
$dog->say();
$dog->run();

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

抽象工厂模式

定义

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

此模式是对工厂方法模式的进一步扩展。在工厂方法模式中,一个具体的工厂负责生产一类具体的产品,即一对一的关系,但是,如果需要一个具体的工厂生产多种产品对象,那么就需要用到抽象工厂模式了。

为了便于理解此模式,这里介绍两个概念:

  • 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  • 产品族 : 在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
角色
  • 抽象工厂(AbstractFactory):担任这个角色的是抽象工厂模式的核心,是与应用系统的商业逻辑无关的。
  • 具体工厂(Factory):这个角色直接在客户端的调用下创建产品的实例,这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统商业逻辑紧密相关的。
  • 抽象产品(AbstractProduct):担任这个角色的类是抽象工厂模式所创建的对象的父类,或它们共同拥有的接口
  • 具体产品(Product):抽象工厂模式所创建的任何产品对象都是一个具体的产品类的实例。
<?php 

interface TV{
  public function open();
  public function use();
}

class HaierTv implements TV
{
  public function open()
  {
      echo "Open Haier TV <br>";
  }

  public function use()
  {
      echo "I'm watching TV <br>";
  }
}

interface PC{
  public function work();
  public function play();
}

class LenovoPc implements PC
{
  public function work()
  {
      echo "I'm working on a Lenovo computer <br>";
  }
  public function play()
  {
      echo "Lenovo computers can be used to play games <br>";
  }
}

abstract class Factory{
  abstract public static function createPc();
  abstract public static function createTv();
}

class ProductFactory extends Factory
{
  public static function createTV()
  {
      return new HaierTv();
  }
  public static function createPc()
  {
      return new LenovoPc();
  }
}

$newTv = ProductFactory::createTV();
$newTv->open();
$newTv->use();

$newPc = ProductFactory::createPc();
$newPc->work();
$newPc->play();

特点与区别

特点

简单工厂模式:

  1. 一个抽象产品类(可以是:接口,抽象类,普通类),可以派生出多个具体产品类。  
  2. 单独一个具体的工厂类。
  3. 每个具体工厂类只能创建一个具体产品类的实例。  

工厂方法模式:

  1. 一个抽象产品类(可以是:接口,抽象类,普通类),可以派生出多个具体产品类。  
  2. 一个抽象工厂类(可以是:接口,抽象类),可以派生出多个具体工厂类。  
  3. 每个具体工厂类只能创建一个具体产品类的实例。  

抽象工厂模式:

  1. 多个抽象产品类(可以是:接口,抽象类,普通类),每个抽象产品类可以派生出多个具体产品类。  
  2. 一个抽象工厂类(可以是:接口,抽象类),可以派生出多个具体工厂类。  
  3. 每个具体工厂类可以创建多个具体产品类的实例。  

区别

  1. 简单工厂模式只有一个抽象产品类,只有一个具体的工厂类。
  2. 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类。
  3. 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个具体产品类的实例。