一般来说,有人告诉我应该注入依赖关系。这种担忧应该分开。应该颠倒那种控制。但为什么呢?
例如,如果我们使用关注点分离但不进行控制反转,该怎么办?为什么这么错?即请参阅下面的代码进行讨论..
class BusinessFunctionality
{
public $motor;
function doStuff()
{
//i.e. at creation time we are not injecting data
//into motor. We create empty motor then set data to it later
$this->motor = new Motor();
//motor loads data into itself
$this->motor->loadMotor();
}
}
class Motor
{
public $motorData;
function loadMotor()
{
$motorData = new MotorData();
//MotorData is another class created to
//separate concerns of Motor functionality
//from database details
//we load up data acquired by MotorData, into Motor
$this->motorData = $motorData->loadMotor();
}
}
class MotorData
{
function loadMotor()
{
//mock Database
$type = "industrial";//$db->query("SELECT... FROM .. ");
return $type;
}
}
//invocation
$business = new BusinessFunctionality();
$business->doStuff();
print "Motor type is " . $business->motor->motorData;
问题:哪种问题会使上述方法容易出现问题?
DataMapper Pattern
为了进行比较,如果我使用依赖注入和控制反转以及关注点分离,我会采用更加倡导的方式,我已经实现了DataMapper
模式,看起来像这样:
//business object
class MyMotor
{
private $data;
function __construct(MotorDataType $data)
{
$this->data = $data;
}
function getType()
{
return $this->data->getType();
}
}
//data mapper object
class MyMotorMapper
{
function getMotorWithData()
{
//get data. i.e from whatever source
$data = (new DatabaseMock())->getData();
//inject data into the object
$motor = new MyMotor($data);
//return motor to the caller
return $motor;
}
}
class MotorDataType
{
private $motorType;
function getType()
{
return $this->motorType;
}
function setMotorType($type)
{
$this->motorType = $type;
}
}
//database object
class DatabaseMock
{
function getData()
{
$data = new MotorDataType();
$data->setMotorType("industrial");
return $data;
}
}
//invocation
$motor = (new MyMotorMapper())->getMotorWithData();
print "Motor type is " . $motor->getType();
我不完全确定我喜欢它的结果,但它展示了我试图展示的原则(DI,SOC,IofC)