PHP工厂方法

Bea*_*use 5 php design-patterns

我正在阅读工厂方法.有人可以解释为什么建议工厂方法位于一个单独的工厂类中吗?

我从这里开始我的例子:http://www.devshed.com/c/a/PHP/Design-Patterns-in-PHP-Factory-Method-and-Abstract-Factory/

class ETF {
  var $data;
  function __construct($data) {
    $this->data = $data;
  }
  function process() {}
  function getResult() {}
}

class VirtualCheck extends ETF {}
class WireTransfer extends ETF {}

class ETFFactory {
  function createETF($data) {
      switch ($data[‘etfType’]) {
      case ETF_VIRTUALCHECK : 
        return new VirtualCheck($data);
      case ETF_WIRETRANSFER :
        return new WireTransfer($data);
      default :
        return new ETF($data);
      }
  }
}

$data = $_POST;
$etf = ETFFactory::createETF($data);
$etf->process();
Run Code Online (Sandbox Code Playgroud)

我倾向于这样写:

class ETF {
    final public static function factory($data) {
        switch ($data[‘etfType’]) {
            case ETF_VIRTUALCHECK :
                return new VirtualCheck($data);
            case ETF_WIRETRANSFER :
                return new WireTransfer($data);
            default :
                return new ETF($data);
        }
    }

    var $data;
    function ETF($data) {
        $this->data = $data;
    }
    function process() {}
    function getResult() {}
}

class VirtualCheck extends ETF {}
class WireTransfer extends ETF {}

$data = $_POST;
$etf = ETF::factory($data);
$etf->process();
Run Code Online (Sandbox Code Playgroud)

这样做我错了吗?

bis*_*hop 4

我不会说你“错了”,但有一种“气味”。通过在制造类中组合工厂方法,该架构违反了一些SOLID准则:

  1. 单一责任:类现在做两件事(当它应该做一件时)。
  2. 开放/封闭原则:班级只半开放(当它应该完全开放时)。
  3. 接口隔离:类的使用者使用制造对象的正确方法,而不使用工厂,反之亦然(当使用者应仅依赖于所需的方法时)

我发现,一个类越坚固,该类就越容易长期维护。因此,我不会认为 SOLID 违规是直接问题,而只是未来可能出现麻烦的信号。

那么,您可能会遇到什么麻烦呢?好吧,如果工厂本身变得更加复杂,您将需要方法来处理额外的工作。这些方法不一定会被类固有方法使用。所以你最终会得到这样的代码:

class ETF {
    final public static factory($kind) {
        switch ($kind) {
        case 'A':
            $etf = static::factoryHelperForA();
            break;
        case 'B':
            $etf = static::factoryHelperForA();
            break;
        }
        return $etf;
    }

    public function apiMethod1() {
        $this->apiMethod1Helper();
    }

    public function apiMethod2() {
        $this->apiMethod2Helper();
    }

    // factory helper
    private static function factoryHelperForA() {
        /* lots of code */
    }

    // another factory helper
    private static function factoryHelperForB() {
        /* lots of code */
    }

    // ugh, now we have api method helpers... totally different responsibility
    private function apiMethod1Helper() {
        /* lots of code */
    }

    // still more...
    private function apiMethod2Helper() {
        /* lots of code */
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以看到,随着工厂需求的增长以及制造业阶级需求的增长,它开始变得混乱。这就是 SOLID 原则引导您远离的事情。

如果现在构建一个未来的灵活类对您很重要,那么我建议将工厂分解为自己的EtfFactory类。