2012-11-09 110 views
2

林建立小MVC,并有一些疑虑,想解决。从另一个类中调用PHP类?

我有调度程序类,该类需要HTTP请求,HTTP响应和路由器类。

我可以做到这一点使用依赖注入,如:

$dispatcher = new Dispatcher($request, $response, $router); 

现在可以说,我不喜欢这种做法,想用Dispatcher类内部类是这样的:

class Dispatcher() 
{ 
    protected $request; 
    protected $response; 
    protected $router; 

    public function __construct() 
    { 
     $this->request = new Request(); 
     $this->response = new Response(); 
     $this->router = new Router(); 
    } 
} 

有什么2方法错误?我正在制定一些面向对象的原则吗?或者这样使用它就好了吗?

回答

1

很难说有什么错误与一种方法或其他。如果不符合要求的规格,这只是错误的。

第一种方法比第二种方法更受欢迎的原因是因为它允许您灵活注入内容。例如:

class Dispatcher { 
    private $req; 
    public function __construct(IRequest $req) { 
     $this->req = $req; 
    } 
} 
interface IRequest {} 
class Request implements IRequest {} 
class MockRequest implements IRequest {} 

//PRODUCTION 
new Dispatcher(new Request); 
//TESTING 
new Dispatcher(new MockRequest); 
+0

不应该是'class CRequest implements IRequest {}'?和'私人$ oReq;'?使其符合您的编码风格。 –

+0

@tereško在界面符号开始处包括一个'I'是一个常见的习惯用法,但它不会延续到其他定义 –

+0

不,实际上这是一种常见的不良做法。接口是**不是**“真的很抽象的类”。接口是合同的定义,接口的名称应描述合同的性质。而不是描述具体实现的类名。 –

0

有你应该使用DI一个原因,你扫视:依赖注入删除从您的代码的依赖关系,并将其抽象给调用者。这使得单元测试代码变得更容易,因为代码本质上不需要外部依赖性来运行。

这是最好的例子。想象一下,如果你的班级需要数据库连接:

class Dispatcher() 
{ 
    protected $db 

    public function __construct() { 
     $this->db = new MysqlDB(); 
    } 
} 

现在,你只是强迫每个人使用MySQL数据库。但是,有你使用DI,你可以抽象的数据库的细节去,仅仅依靠一些类代表一个数据库对象:

class Dispatcher() 
{ 
    protected $db 

    public function __construct(Database $db) { 
     $this->db = $db; 
    } 
} 

然后,你定义一些对象代表不同的数据库连接:

现在
interface Database { 
    public function query($sql); 
} 

class MySQLDB implements Database { 
    public function query($sql) { // Stuff for MySQL 
    } 
} 

class OracleDB implements Database { 
    public function query($sql) { // Stuff for Oracle 
    } 
} 

,用户是否做到:

$dispatcher = new Dispatcher(new MysqlDB()); 

或者:

$dispatcher = new Dispatcher(new OracleDB()); 

这没关系 - 同一个类可以重复使用这两个数据库。

+0

为什么'Dispatcher'需要数据库实例?这就像给狗狗钉腿并称之为“章鱼”。 –

0

第二个示例会导致Dispatcher类和它使用的所有3之间的紧密耦合。如果你正在寻找一个特定的法律或原则,这是违反了这一点,它会是open/closed principle

P.S:你确定taht您使用事件驱动的架构?因为这是唯一的context其中我发现调度员提到。

0

第二个例子应该用后缀被调用,因为它产生的其他对象。

在这两个例子中,你最终得到高耦合Dispatcher对象(Dependancy inversion

调度员应该能够只要求接口或服务,即其他对象实行/被注册到。