Php,静态方法和继承..用于搜索有效模式

时间:2011-08-23 09:47:21

标签: php inheritance static design-patterns

实现此行为的最佳模式是什么?

我有很多方法,比如method_1 .. method_N,可以通过一个参数进行参数化,比如$ k。我想把它们作为静态方法放在一个类中,所以当然我可以像这样编写我的ComputationClass:

class Computation {
    static function method1( $k, $otherParams ) { ... }
    static function method2( $k, $otherParams ) { ... }
    static function method3( $k, $otherParams ) { ... }
}        

现在,由于$ k属于特定范围的值,比如{'dog','cat','mouse'},我想创建许多Computation的子类,每个可能的值都有一个。

class Computation_Dog extends Computation {
    static function method1( $otherParams ) { parent::method1('dog', $otherParams); }
    static function method2( $otherParams ) { parent::method2('dog', $otherParams); }
    static function method3( $otherParams ) { parent::method3('dog', $otherParams); }
}
class Computation_Cat extends Computation { .. }
class Computation_Mouse extends Computation { .. }

但这非常难看,让我放弃了继承的优势:如果我向计算中添加一个方法会发生什么?必须编辑所有子类.. 然后我巧妙地切换到了这个:

abstract class Computation {
    abstract static function getK();

    static function method1($otherParams) { ... self::getK() .. }
    static function method2($otherParams) { ... self::getK() .. }
    static function method3($otherParams) { ... self::getK() .. }
}

class Computation_Dog extends Computation {
    static function getK() { return 'dog'; }
}

很好的尝试,但它不起作用,因为静态方法似乎不记得继承栈,而self :: getK()会调用Computation :: getK()而不是Computation_Dog :: getK()。 / p>

嗯..希望足够清楚......你会如何设计这种行为? PS:我真的需要它们作为静态方法

由于

3 个答案:

答案 0 :(得分:1)

我根本不会设计这种行为。如果你需要调用parent :: Method1('dog'),这意味着parant显然知道计算狗。您的Calculating_Dog类只是一个包含shorthands的愚蠢类。

是的,如果你向基类添加一个方法,你必须将它添加到所有其他类。

如果你有实例而不是静态类,你可以在包含计算类型的类中添加一个属性。然后,您将不需要长函数。您可以将简写函数添加到基类,并使用属性而不是参数。 您可以为此类提供受保护的构造函数,并将其传递给正确的类型。

然后,您可以创建具有不带参数的构造函数的后代,该参数将所需类型作为参数调用其父级构造函数。 然后,对这些后代进行单例引用。

这将是一种接近你想要的方式。但我需要看到或听到您实际想要达到的目标,以确定这是否是最佳解决方案。

[编辑]

您可以使用__callStatic(来自PHP 5.3)来捕获不存在的方法的静态方法调用。然后,您可以将额外的“dog”参数卸载到属性的开头,并调用Calculate基类。这里展示了两种方式:

/* METHOD 1 Use __callStatic and make the parent function protected
   to hide them. Else __callStatic won't work. */
class Calculate1
{
    protected static function Method1($type, $param)
    {
        echo "Retrieving call for $type with param $param.";
    }
}

class Calculate_wrapper1 extends Calculate1
{
    static function __callStatic($functionName, $attributes)
    {
        array_unshift($attributes, 'dog');
        var_dump($attributes);
        // using get_parent_class()
        return call_user_func_array(array(get_parent_class(), $functionName), $attributes);
    }
}

Calculate_wrapper1::Method1('String');

/* METHOD 2 Don't inherit the wrapper from Calculate. This way the methods of
   Calculate itself can (must!) be public. */
class Calculate2
{
    public static function Method1($type, $param)
    {
        echo "Retrieving call for $type with param $param.";
    }
}

class Calculate_wrapper2
{
    static function __callStatic($functionName, $attributes)
    {
        array_unshift($attributes, 'dog');
        var_dump($attributes);
        // using the fixed class name
        return call_user_func_array(array('Calculate2', $functionName), $attributes);
    }
}

Calculate_wrapper2::Method1('String');

答案 1 :(得分:0)

我不确定我是否完全理解代码,但我认为您的问题的解决方案是使用Late Static Bindings

但是,如果您可以更准确地了解这些方法的具体用途,我们可能会为您提供更好的整体解决方案。

答案 2 :(得分:0)

从php5.3开始,您可以使用Late Static Bindings.Use static::getK()而不是self::getK()Late Static Bindings