从UML角度理解依赖

什么是依赖

简单的理解就是,一个类A用到了另一个类B,这种使用关系是具有偶然性的,临时性的,非常弱的,但是当类B发生变化时,又会影响到类A。
举个例子:


图1

我们有一个Customer的Controller,它需要完成对Customer的查找或新增,如果我们用EF进行数据库操作的话,CustomerController就会对数据库的Context有一个依赖的关系。

显式依赖与隐式依赖

要解释这个的话,还是看代码比较直接。

[Route("customer")]
public class CustomerController:Controller
{
    [HttpPost]
    [Route("add")]
    public IActionResult Add([FromBody]Model.Customer customer)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        var context=new CustomerContext(new DBContextOptions<CustomerContext>{});
        var result=context.Customers.SingleOrDefault(c=>c.Phone=customer.Phone);
        if(result!=null)
        {
            return BadRequest(new {code=1001,message="手机号码已存在"});
        }
        context.Customers.Add(customer);
        context.SaveChanges();
        return Ok();
    }

    [HttpGet]
    [Route("detail")]
    public IActionResult Detail(int id)
    {
        var context=new CustomerContext(new DBContextOptions<CustomerContext>{});
        var customer=context.Customers.SingleOrDefault(c=>c.Id=id);
        if(result==null)
        {
            return NotFound();
        }
        return Json(customer);
    }
}

这种代码编写方式是隐式依赖。
再来看:

[Route("customer")]
public class CustomerController:Controller
{
    private CustomerContext _context;
    public CustomerController()
    {
        _context=new CustomerContext(new DBContextOptions<CustomerContext>{});
    }

    [HttpPost]
    [Route("add")]
    public IActionResult Add([FromBody]Model.Customer customer)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        var result=_context.Customers.SingleOrDefault(c=>c.Phone=customer.Phone);
        if(result!=null)
        {
            return BadRequest(new {code=1001,message="手机号码已存在"});
        }
        context.Customers.Add(customer);
        context.SaveChanges();
        return Ok();
    }

    [HttpGet]
    [Route("detail")]
    public IActionResult Detail(int id)
    {
        var customer=_context.Customers.SingleOrDefault(c=>c.Id=id);
        if(result==null)
        {
            return NotFound();
        }
        return Json(customer);
    }
}

这种就是显式依赖。

依赖倒置

高层业务不依赖于低层业务的具体实现,而依赖于具体的抽象。上面的UML图可以修改如下:


图2

将来,如果不适用EF,而改用其他方式的话,UML图可改动如下:


图3

这就实现了依赖倒置,具体代码如下:

[Route("customer")]
public class CustomerController:Controller
{
    private ICustomerRepository _customerRepository;
    public CustomerController()
    {
        _customerRepository=new EFCustomerRepository(new DBContextOptions<CustomerContext>{});
    }

    [HttpPost]
    [Route("add")]
    public IActionResult Add([FromBody]Model.Customer customer)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        var result=_customerRepository.GetPhone(customer.Phone);
        if(result!=null)
        {
            return BadRequest(new {code=1001,message="手机号码已存在"});
        }
        _customerRepository.Insert(customer);
        return Ok();
    }

    [HttpGet]
    [Route("detail")]
    public IActionResult Detail(int id)
    {
        var customer=_customerRepository.GetById(id);
        if(result==null)
        {
            return NotFound();
        }
        return Json(customer);
    }
}

控制反转

将控制权交出去,代码如下:

    private ICustomerRepository _customerRepository;
    public CustomerController(ICustomerRepository customerRepository)
    {
        _customerRepository=customerRepository;
    }

这样,你既可以传EFCustomerRepository,也可以传MemoryCustomerRepository了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容