什么是依赖
简单的理解就是,一个类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了。
网友评论