PHP开发PHP经验分享

编程中的设计模式之工厂模式

2020-07-06  本文已影响0人  phpworkerman
介绍

工厂模式(Factory Pattern)属于设计模式中的创建型模式,它提供了一种创建对象的最佳方式。定义一个创建对象的接口,通过子类来完成对象的实例化,代码层面只提供实例化类的名称,无需关心实例化的过程,降低业务代码和创建对象的耦合。工厂模式又分为三种模式,简单工厂模式、工厂方法模式、抽象工厂模式。

简单工厂模式

模拟一个业务使用场景,现在要根据文件后缀来设置不同的处理方法,比如后缀为 .doc 的文件和后缀为 .xlsx 的文件都需要用 handleFile 方法处理,可以定义一个接口 File 在里边规定 handleFile 方法,代码示例如下:

<?php
interface File
{
  public function handleFile();
}

class DocFile implements File
{
  public function handleFile()
  {
    echo 'doc 文件的处理方式';
  }
}

class XlsxFile implements File
{
  public function handleFile()
  {
    echo 'xlxs 文件的处理方式';
  }
}
//创建工厂类,通过调用静态方法完成类的实例化
class ChooseFile
{
  public static function createDoc()
  {
    return new DocFile();
  }

  public static function createXlxs()
  {
    return new XlsxFile();
  }
}
//调用 Doc 文件的处理方法
$doc = ChooseFile::createDoc();
$doc->handleFile();
//调用 Xlxs 文件的处理方法
$xlxs = ChooseFile::createXlxs();
$xlxs->handleFile();

通过这个例子可以看到,根据客户端的选择,可以实例化不同的类,可以使业务代码和接口完成解耦,但是该模式违反了面向对象编程原则中的 开放封闭原则(Open Closed Principle) ,并且只有一个工厂类负责所有方法的实现,如果后期需要扩展,只能修改工厂类,静态方法也无法继承,注定了该模式只适合实例化类少或是较为简单的应用场景。

关于开放封闭原则的知识补充

该原则的是面向对象编程的核心,对扩展开放,对修改封闭。软件需求总是会发生变化的,对应用的扩展是软件设计必须考虑的,减少对类的修改可以增强类的独立性,降低代码之间的耦合。在上边的例子中,ChooseFile 提供一个对客户端的访问接口,是一个已完成的类,如果需要引入其他的文件处理方式,就需要修改这个工厂类,这就违反了“对修改封闭”的原则。

工厂方法模式

常说的工厂模式,其实就是该模式,因为解决了简单工厂模式中的开放封闭原则的问题,扩展更加方便,所以使用最多。还以上边提到的应用场景为例,我们现在如果要加入新的文件格式 .php ,通过改造工厂类,定义接口,具体的类实例化工作由子类完成,如果需要添加扩展,就新增文件处理的扩展类和工厂子类示,例如下:

<?php
interface File
{
  public function handleFile();
}

class DocFile implements File
{
  public function handleFile()
  {
    echo 'doc 文件的处理方式';
  }
}

class XlsxFile implements File
{
  public function handleFile()
  {
    echo 'xlxs 文件的处理方式';
  }
}
//新增PHP文件的处理类
class PhpFile implements File
{
  public function handleFile()
  {
    echo 'PHP 文件的处理方式';
  }
}

//创建工厂接口,由子类实现接口的方法
interface CreateFile
{
  public function getInstance();
}

class CreateDoc implements CreateFile
{
  public function getInstance()
  {
    return new DocFile();
  }
}

class CreateXlsx implements CreateFile
{
  public function getInstance()
  {
    return new XlsxFile();
  }
}

class CreatePhp implements CreateFile
{
  public function getInstance()
  {
    return new PhpFile();
  }
}
//doc
$doc = new CreateDoc();
$docFile = $doc->getInstance();
$docFile->handleFile();
//xlsx
$xlsx = new CreateXlsx();
$xlsxFile = $doc->getInstance();
$xlsxFile ->handleFile();
//php
$php = new CreatePhp();
$phpFile = $php->getInstance();
$phpFile ->handleFile();

工厂方法模式解决了开闭原则的问题,扩展不需要修改原有代码,但是增加越多的文件处理方式,就需要同步增加相应的文件处理类和工厂子类,类的数量增加会带来系统复杂度的提升。

抽象工厂模式

相比工厂方法模式,该模式进一步对代码进行了抽象,通过接口的形式对产品进行归纳约束,并再通过抽象类组合多种产品,形成完整的对象,如下例子:
1.先是定义了文件接口 TextFile、系统接口 System;
2.再对每个接口具体实现 DocFile 、XlsxFile 、Windows 、Mac ;
3.定义抽象类 AbstractFactory,描述文件类和系统类的关系;
4.再对抽象类具体实现 WinFile 、MacFile;
5.创建类的构造器 FactoryFile->getFactory();
6.工厂输出产品。

<?php
//定义文件接口
interface TextFile
{
    public function read();
    public function write();
}
//Doc文件处理类的具体实现
class DocFile implements TextFile
{
    public function read()
    {
        echo 'doc read';
    }

    public function write()
    {
        echo 'doc write';
    }
}
//Xlsx文件处理类的具体实现
class XlsxFile implements TextFile
{
    public function read()
    {
        echo 'xlsx read';
    }

    public function write()
    {
        echo 'xlsx write';
    }
}
//系统接口定义
interface System
{
    public function upload();
}
//windows 系统类具体实现
class Windows implements System
{
    public function upload()
    {
        echo '上传到 Windows';
    }
}
//Mac 系统类具体实现
class Mac implements System
{
    public function upload()
    {
        echo '上传到 Mac OS';
    }
}
//定义抽象类,描述文件和系统的关系
abstract class AbstractFactory
{
    abstract public function getFile($fileType);
    abstract public function getSystem($systemType);
}
//windows 操作系统的抽象类实现
class WinFile extends AbstractFactory
{
    public function getFile($fileType)
    {
        return new $fileType;
    }

    public function getSystem($systemType)
    {
        return new $systemType;
    }
}
//Mac 操作系统的抽象类实现
class MacFile extends AbstractFactory
{
    public function getFile($fileType)
    {
        return new $fileType;
    }

    public function getSystem($systemType)
    {
        return new $systemType;
    }
}
//实例化抽象类的子类
class FactoryFile
{
    public function getFactory($factory)
    {
        return new $factory;
    }
}
//测试类
class Client
{
    public function getInfo()
    {
        $factoryFile = new FactoryFile();
        $winFactory = $factoryFile->getFactory('WinFile');
        $docFile = $winFactory->getFile('DocFile');
        $docFile->read();
        $docFile->write();
        $system = $winFactory->getSystem('Windows');
        $system->upload();
    }
}

$client = new Client();
$client->getInfo();

抽象工厂模式是三种模式里最难理解的一种,并且该模式的扩展会违反开闭原则,它适合用来描述工厂中多产品之间的关联。

上一篇下一篇

猜你喜欢

热点阅读