【问题标题】:Abstract Factories not possible in php < 5.3?php < 5.3 中不可能有抽象工厂?
【发布时间】:2011-03-29 15:04:52
【问题描述】:

我正在研究一个抽象类,以便为几个类节省一些代码。这些类都是通过不同的静态调用实例化自己的工厂。我可以通过将所有这些方法放在一个抽象类中来节省一些代码。

但是,我遇到了后期静态绑定问题...由于我们的网络主机未使用 5.3 或更高版本,我无权访问 get_call_class。如果我有

$class = __CLASS__;
return new $class();

在抽象类中,__CLASS__ 是抽象类的名称,当我真正希望它使用被调用的类时。

我在 Web 上看到了抽象工厂的示例,其中子类具有自己的实例化方法,并且不依赖于抽象父类。然而,在这种情况下,抽象类的唯一原因是为了节省代码,所以如果我不能在那里做,它的价值就会大大降低。

php debug_backtrace()?


编辑:

我做了一个测试,似乎debug_backtrace() 不起作用!我想这就是为什么我们需要后期静态绑定

<?

abstract class abstractFactory {
    public function create() {
            print_r(debug_backtrace());
            $class = __CLASS__;
            return new $class();
    }
}

class concreteFactory extends abstractFactory {}

$chimborazo = concreteFactory::create();

结果:

$ php test.php
Array
(
    [0] => Array
        (
            [file] => /var/www/test.php
            [line] => 13
            [function] => create
            [class] => abstractFactory
            [type] => ::
            [args] => Array
                (
                )

        )

)

Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7

【问题讨论】:

    标签: php abstract-class factory-pattern late-static-binding


    【解决方案1】:

    一种方法是重写各种实例化方法,并直接传递类的名称:

    <?
    
    abstract class abstractFactory {
    
        public function create($class) {
            return new $class();
        }
    
        public function instantiate($class) {
            return new $class();
        }
    
    }
    
    class concreteFactory extends abstractFactory {
    
        public function create() {
            parent::create(__CLASS__);
        }
    
        public function instantiate() {
            parent::instantiate(__CLASS__);
        }
    }
    
    
    $chimborazo = concreteFactory::create();
    $chimborazo = concreteFactory::instantiate();
    

    【讨论】:

    【解决方案2】:

    这是我在迁移到 5.3 之前一直在使用的:

    if (!function_exists('get_called_class')) {
    
       /**
        * Implementation of get_called_class() for pre-5.3 PHP
        *
        * @return string
        */
       function get_called_class()
       {
          $bt = debug_backtrace();
          $lines = file($bt[1]['file']);
          preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
                   $lines[$bt[1]['line']-1],
                   $matches);
          return $matches[1];
       }
    }
    

    这使您可以在静态函数中确定调用该函数的类名。这是一种存在一些性能问题的解决方法,但它是我发现的唯一一个。如果还有其他的我很想知道。

    【讨论】:

      【解决方案3】:

      我见过的唯一解决方法是调用debug_backtrace 来确定调用者的类名。这当然是一个巨大的黑客。我见过一些代码结合了回溯与实际上打开调用文件并解析它来解决问题。奇怪,可怕的东西。

      LSB 的缺失会在稍后卷土重来。立即升级,即使这意味着切换主机。事实上,特别是如果这意味着切换主机。 5.3 已经发布一年了。

      【讨论】:

      • 我做了一个测试,在抽象 create() 属性中调用 debug_backtrace() 没有引用原始类的元素!我认为它会在那里,但我想这就是我们需要后期静态绑定的原因:P
      猜你喜欢
      • 1970-01-01
      • 2011-09-08
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多