2

7 个月以来,我一直在开发一个用 PHP 和 MySQL 编写的 PBBG(游戏)。该项目即将完成,可能很快就会发布,但我担心一些问题。

这是我第一次编写真正的项目,也是我第一次使用 OOP。我的代码现在有大约 25k 行,这是我的问题:

我是否正确使用 OOP?我相信我过度调用类构造。我有大约 20 个不同的班级,有时他们需要彼此。这是我如何使用 OOP 的示例代码:(只是一个草图,可能不起作用)

class A {
    
    public $b;
    public $c;

    public function __construct(){
        $b = new B();
        $c = new C();
    }

    public function sampleA(){
        //some stuff that depends $c->sampleC
    }

}

class B { 

    public $c;

    public function __construct(){
        $c = new C();
    }

    public function sampleB($id){
        return $this->c->sampleC($id);
    }

}

class C {

    public function sampleC(){

    }

}

然后我会使用:

$a = new A();
$b = new B();
$c = new C();

$whatIWant = $a->sampleA($b->sampleB($c->sampleC()));

虽然我可以

$a = new A();
$whatIWant = $a->sampleA($a->b->sampleB($a->c->sampleC()));

在这个简单的示例中,这看起来没有必要,但我的脚本中有 200 多个不同的构造函数调用,我想这会减慢并超载我的服务器。

也许我的例子不是很清楚,所以我打印了我的 xdebug 分析器结果:

打印

我需要单身吗?我尝试在单例中使用这样的简单示例,但我得到了相同的结果(每个类超过 1 个构造)。
也许我需要扩展这些类并使用父类的构造函数?但是 20 个不同的类,有时是独立的,有时是相互依赖的,这怎么可能呢?
或者也许我以正确的方式使用它(我不这么认为)

4

2 回答 2

3

我不会那样做的。我会这样做的方式是使用依赖注入。我已将类中的实例设置为protected(或将它们设置为private)。无需将它们设为公开。如果你认为你需要你几乎肯定违反了一些规则,你需要重新考虑你的设计。

我改变的另一件事是你做了$b = new B()。这有两个问题:

  1. 我想你打算这样做$this->b = new B()
  2. 您正在将该B类与另一个类紧密耦合。

这使得无法进行任何单元测试,因为您不能B用模拟类替换该类。因此,不是测试单元(类),而是测试多个类。

我做的另一件事是类型提示构造函数参数。当您有类的接口时,这将更加有用。这也使得测试类变得更加容易。另请参阅此相关答案

您可能感兴趣的一些视频:依赖注入单元测试继承、多态性和测试。您可能还想阅读一些关于SOLID 编程的内容。您的代码似乎也违反了LoD,这意味着您正试图通过其他对象访问内容。

这样的事情是我会做的:

class A
{
    protected $b;
    protected $c;

    public function __construct(B $b, C $c)
    {
        $this->b = $b;
        $this->c = $c;
    }

    public function sampleA()
    {
        $this->c->sampleC();
    }
}

class B
{     
    protected $c;

    public function __construct(C $c)
    {
        $this->c = $c;
    }

    public function sampleB($id)
    {
        return $this->c->sampleC($id);
    }
}

class C
{    
    public function sampleC() { }
}

$b = new B();
$c = new C($b);
$a = new A($b, $c);

$whatIWant = $a->sampleA();

如果你想编写正确的 OOP 代码,你永远不应该(恕我直言)使用 signleton 反模式。基本上它只是另一个名称(具有相同的特征)作为global.

也许我需要扩展这些类并使用父类的构造函数?但是 20 个不同的类,有时是独立的,有时是相互依赖的,这怎么可能呢?

只有当子类可以替代父类时,您才应该扩展类。这在 SOLID中称为Liskov 替换原则。换句话说,您必须能够说class childis a class parent

于 2012-09-03T19:23:24.973 回答
2

您需要的是结合依赖注入的控制反转模式。

使用这些模式,您可以使您的类保持松散耦合,并强制每个类都使用正确的类和参数构造。

大多数优秀的 PHP 框架都有 IoC 和 DI 实现。查看 Symphony 的本教程

于 2012-09-03T19:21:42.480 回答