我正确使用OOP吗?

时间:2012-09-03 19:14:18

标签: php oop singleton

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

这是我第一次编写一个真实的项目,也是我第一次使用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 profiler结果:

Print http://img820.imageshack.us/img820/2166/possiblensting.jpg

单身是我需要的吗?我尝试使用像singleton这样的简单示例,但我有相同的结果(每个类超过1个构造) 也许我需要扩展这些类并使用父的构造函数?但是,如何才能实现20个不同的阶级,有时是独立的,有时是彼此依赖的? 或者也许我正在以正确的方式使用它(我不这么认为)

2 个答案:

答案 0 :(得分:3)

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

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

  1. 我认为你打算做$this->b = new B()
  2. 您正在将B类与其他类紧密耦合。
  3. 这使得无法进行任何单元测试,因为您无法用模拟类替换B类。因此,不是测试单元(类),而是测试多个类。

    我做的另一件事是键入提示构造函数参数。当您拥有类的接口时,这将更加有用。这也使得测试类变得更加容易。另请参阅this related answer

    您可能感兴趣的一些视频:Dependency InjectionUnit testingInheritance, Polymorphism, & Testing。您可能还想阅读一些关于SOLID programming的内容。您的代码似乎也违反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代码,你不应该(imho)使用signleton反模式。基本上它只是global的另一个名称(具有相同的特征)。

      

    也许我需要扩展这些类并使用父的构造函数?但是,如何才能实现20个不同的阶级,有时是独立的,有时又相互依赖?

    只有在子类可以替换父类时才应该扩展类。这在SOLID中称为Liskov substitution principle。换句话说,您必须能够说class childclass parent

答案 1 :(得分:2)

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

使用这些模式,您可以使您的类失去耦合,并强制每个类都使用正确的类和参数构建。

大多数优秀的PHP框架都有IoC和DI实现。从Symphony看这个tutorial