我一直在开发一个用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个不同的阶级,有时是独立的,有时是彼此依赖的? 或者也许我正在以正确的方式使用它(我不这么认为)
答案 0 :(得分:3)
我不会那样做。我这样做的方法是使用依赖注入。我已将类中的实例设置为protected
(或将它们设置为private
)。没有必要公开它们。如果你认为你需要它几乎肯定违反了一些规则,你需要重新考虑你的设计。
我改变的另一件事是你$b = new B()
。这有两个问题:
$this->b = new B()
B
类与其他类紧密耦合。这使得无法进行任何单元测试,因为您无法用模拟类替换B
类。因此,不是测试单元(类),而是测试多个类。
我做的另一件事是键入提示构造函数参数。当您拥有类的接口时,这将更加有用。这也使得测试类变得更加容易。另请参阅this related answer。
您可能感兴趣的一些视频:Dependency Injection,Unit testing,Inheritance, 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 child
是class parent
。
答案 1 :(得分:2)
您需要的是控制反转模式与依赖注入相结合。
使用这些模式,您可以使您的类失去耦合,并强制每个类都使用正确的类和参数构建。
大多数优秀的PHP框架都有IoC和DI实现。从Symphony看这个tutorial。