首先,当使用参数是对象的方法时,需先实例化对象,再传给它(方法)。如下所示
var product = new Product();
createShipment(product);
于是,我们说:createShipment方法依赖Product类,而Product类注入给createShipment方法。
然而,当createShipment方法需要多个参数时,则
//实例化对象start
var product = new Product();
var shipCompany = new ShipCompany();
var adress = new Adress();
var order = new Order();
order.setAddress(address);
//实例化对象end
createShipment(product,shipCompany,order);
依赖注入(dependency injection , DI)解决了实例化对象这个冗长的步骤。在依赖注入中,createShipment方法不需明确实例化参数对象,参数对象会在外部机制注入,createShipment方法只需声明,我需要这些参数对象。
控制反转(inversion of control , IOC),将依赖的控制权从内部转到外部,实现控制反转模式的框架称为IOC容器,则Angular是IOC容器。
依赖注入和控制反转的关系:
依赖注入和控制反转是一体两面的概念,控制反转是目的,而依赖注入是手段,Angular就是使用了“依赖注入”手段,实现了控制反转的目的。
var product = new Product();
createShipment(product);
//如果把createShipment方法中的参数product对象类改成MockProduct,则需改变其内部代码new的过程
var product = new MockProduct();
createShipment(product);
而,依赖注入只需声明,我需要一个product参数,至于这个参数是来源于Product类还是MockProduct类,与我无关,只需交付给外部代码操作。
松耦性,可重用性和可测试性高
假设有一个productComponent组件,需要一个ProductService服务,在传统的写法中,使用new实例化
var productService= new ProductService();
然而,当需要更改服务为AnotherProductService时,则
var productService= new AnotherProductService();
这说明,productComponent组件和ProductService服务紧密的耦合一起。
而使用依赖注入时(以下也是使用依赖注入的步骤)
@NgModule({
providers:[ProductService]
//等价于
//providers:[{provide:ProductService,useClass:ProductService}]
})
export class AppModule { }
@Component({
...省略组件配置
})
export class ProductComponent{
product:Product;
constructor(productService:ProductService){
this.product = productService.getProduct();
}
}
而当需要更改服务为AnotherProductService时,只需更改providers中的声明,消除了ProductComponent和ProductService的耦合性。
@NgModule({
providers:[{provide:ProductService,useClass:AnotherProductService}]
})
export class AppModule { }
1.在AppModule中的声明一个provider,注册一个类型为ProductService的token
2.当ProductComponent组件的构造函数声明自己需要一个ProductService类型的token,就会有provider注入进来
不要着急,最好的总在最不经意的时候出现。 ——泰戈尔