Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/245.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从另一个类内部调用PHP类?_Php_Oop - Fatal编程技术网

从另一个类内部调用PHP类?

从另一个类内部调用PHP类?,php,oop,Php,Oop,我正在构建小型MVC,有一些疑问需要解决 我有一个dispatcher类,这个类需要HTTP请求、HTTP响应和路由器类 我可以使用依赖项注入这样做: $dispatcher = new Dispatcher($request, $response, $router); 现在让我们假设我不喜欢这种方法,并且希望在Dispatcher类中使用如下类: class Dispatcher() { protected $request; protected $response;

我正在构建小型MVC,有一些疑问需要解决

我有一个dispatcher类,这个类需要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方法是否有问题?我有没有违反OOP原则?还是这样使用就可以了?

很难说一种方法或另一种方法有什么问题。只有不符合要求的规格才是错误的

第一种方法优于第二种方法的原因是,它允许您灵活地注入内容。例如:

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);

您应该使用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
类和它使用的所有3个类之间紧密耦合。如果你正在寻找一个特定的法律或原则,这是违反了这一点,它将是

p.S.:您确定使用的是事件驱动架构吗?因为这是我唯一提到的


第二个示例应使用工厂后缀调用,因为它创建了其他对象

在这两个示例中,最终都会得到一个高度耦合的Dispatcher对象()


Dispatcher应该能够请求其他对象实现/注册到的接口或服务。

为什么
Dispatcher
需要数据库实例?这就像把狗的腿钉在钉子上,然后叫它“章鱼”。难道不是
类CRequest实现了IRequest{}
?和
private$oReq?为了使您的编码风格保持一致,tereško在界面符号的开头包含一个
I
,这是一种常见的习惯用法,但它不会延续到其他定义。不,实际上这是一种常见的错误做法。接口不是“真正的抽象类”。接口是合同的定义,接口名称应描述所述合同的性质。而不是描述一个具体实现的类名。@tereško那么你会怎么称呼它呢?可请求?这取决于接口需要什么方法。
$dispatcher = new Dispatcher( new OracleDB());