我正在构建小型MVC,并且有一些想要解决的疑问。
我有调度程序类,该类需要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原则?或者这样使用它就好了吗?
答案 0 :(得分: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);
答案 1 :(得分: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());
没关系 - 同一个类可以重用于两个数据库。
答案 2 :(得分:0)
第二个例子导致Dispatcher
类与它使用的所有3个类之间紧密耦合。如果您正在寻找具体的法律或原则,那就违反了这一点,那将是open/closed principle。
P.S。:您确定使用的是事件驱动架构吗?因为这是我发现 Dispatcher 的唯一context。
答案 3 :(得分:0)
应使用 Factory 后缀调用第二个示例,因为它会创建其他对象。
在这两个示例中,您最终得到一个高耦合Dispatcher对象(Dependancy inversion)
Dispatcher应该能够只询问其他对象实现/注册的接口或服务。