根据条件参数

时间:2015-12-11 14:09:02

标签: php oop design-patterns

我需要一些代码设计方面的帮助。我有一个用于许多项目的包。

$p = new Package();
$result = $p->method();

虽然Package看起来像:

class Package {
    public function method($fooArg = 1, $barArg = 1)
    {
        // some logic

        return new SomeClass(
            $fizzArg,
            $buzzArg
        );
    }
}

现在,在一个使用Package的项目中,我需要更改返回的类。所以,电话会是这样的:

$p = new Package();
$result = $p->method(10, 10, true);

Package将如下所示:

class Package {
    public function method($fooArg = 1, $barArg = 1, $condArg = false)
    {
        // some logic

        if (false === $condArg) {
            return new SomeClass(
                $fizzArg,
                $buzzArg
            );
        }

        return new MyNewClass(
            $fizzArg,
            $fooBarArg
        );
    }
}

这里应该使用哪种设计模式?我不想根据条件返回不同的对象类型,因为它对我来说似乎很难看。

5 个答案:

答案 0 :(得分:3)

由于您从调用脚本显式设置$condArg并且它是控制返回哪个实例的唯一参数,因此请考虑创建第二个公共方法以返回MyNewClass,并提取{{1} }私有方法在两个公共方法之间共享:

some logic

答案 1 :(得分:2)

这可以通过工厂和依赖注入模式的组合来解决:

以下示例有点冗长,但它说明了基本原则。通过为您的Package课程提供由特定项目实施的工厂。您不需要更改该类的代码。相反,更改是通过接口进行抽象的。

/*
 * Shared library
 */

interface IEntity
{

}

interface IFactory
{
    /**
     * @param $arg1
     * @param $arg2
     * @return IEntity
     */
    public function create($arg1, $arg2);
}

class Package
{
    protected $factory;

    public function __construct(IFactory $factory)
    {
        $this->factory = $factory;
    }

    public function method($arg1, $arg2)
    {
        return new $this->factory->create($arg1, $arg2);
    }
}

/*
 * Project A
 */

class FactoryA implements IFactory
{
    public function create($arg1, $arg2)
    {
        return new EntityA();
    }
}

class EntityA implements IEntity
{
    public function construct($arg1, $arg2)
    {

    }
}

/*
 * Project B
 */

class FactoryB implements IFactory
{
    public function create($arg1, $arg2)
    {
        return new EntityB();
    }
}

class EntityB implements IEntity
{
    public function construct($arg1, $arg2)
    {

    }
}

答案 2 :(得分:2)

从纯粹的理论角度来看,使用这样一个包必须根据其使用位置返回其他东西的想法是非常难看的。这意味着广泛使用的包依赖于使用它的包的细节,这对我来说是一个信号,你必须完全废弃这个想法,而不是在这个项目中使用这个包。

答案 3 :(得分:0)

您的包似乎是this answer,它根据参数构建对象。如果我做对了,现在你想为不同的项目使用不同的对象。

Factory method就是你要找的。

让你的包抽象化。有两个实现,并在启动阶段加载正确的包,您可以使用反射或配置或PHP允许您执行的任何操作。

注意:您的Package类中似乎还有一些其他逻辑,如果该逻辑独立于构建对象,则将其提取到另一个类,反之亦然。

答案 4 :(得分:0)

由于您无法使用访问所有项目,并且您可以更改的来源(如果它不影响其他项目),那么它会更安全改为创建的后代。这样,您可以在不影响其他项目的情况下更改现有方法,还可以添加新方法。

include('package.php');

class myPackage extends Package(){
  public function newMethod($arg1, $arg2){
    return new otherClass($arg1, $arg2);
  }

  //if you want to change existing method
  public function method($fooArg = 1, $barArg = 1){
    //some new logic
  }
}

然后你可以在你的项目中使用它:

$obj = new myPackage();
if ($i_want_regular_class){
  $newObj = $obj->method(1, 2); // call parent's method or modified parent's method
} else {
  $newObj = $obj->newMethod(3, 4); // call new method
}

至于为什么我建议你创建新方法是因为你已经知道要创建哪个对象,因此传递给方法的参数。所以不是把条件放在方法中,为什么不把条件放在逻辑中并调用适当的方法呢?