doutao1282 2015-06-29 15:21
浏览 22

为什么将依赖关系绑定到业务对象是错误的?

In general, it has been told to me that dependencies should be injected. That concerns should be separated. That control should be inverted. But why?

For example, what if we use separation of concerns but don't do inversion of control. Why is it so wrong? i.e. see code below for discussion..

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;

Question: What are the problems that will make the approach above prone to issues?

DataMapper Pattern

For comparison purposes, a more advocated way ios if I use dependency injection and inversion of control and separation of concerns, I have implemented a DataMapper pattern to look something like this:

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

Not entirely sure I like the way it turned out, but it demonstrates the principles I am trying to show (DI, SOC, IofC)

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥50 potsgresql15备份问题
    • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
    • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
    • ¥60 pb数据库修改与连接
    • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
    • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
    • ¥20 神经网络Sequential name=sequential, built=False
    • ¥16 Qphython 用xlrd读取excel报错
    • ¥15 单片机学习顺序问题!!
    • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上