一、什么是IOC(控制反转)?
控制反转是一种软件设计原则,它将控制权从一个模块或对象转移到另一个模块或对象,从而实现了松耦合。在IOC中通常由容器来控制程序流程,而不是由程序员直接控制。
IOC的主要思想是将程序的控制权交给容器,容器负责实例化对象、管理对象的生命周期,并将对象之间的依赖关系注入到对象中。这样做的好处是降低了各组件之间的耦合度,提高了代码的可维护性和可测试性。
举例:下面定义了一个接口Service,然后定义了一个实现类ServiceImpl实现了接口中的execute方法,还定义了一个IocContainer类里面定义了一个Map当作容器,Map的键为bean名,值为bean,可以往Map中存入或取出bean,在main方法中现在不是直接new一个ServiceImpl对象,而是将ServiceImpl对象存入到容器中,在需要的时候可以取出,Client类在这里采用了构造函数来注入依赖,可以通过注入的不同依赖输出不同的结果。
public interface Service {
void execute();
}
public class ServiceImpl implements Service {
@Override
public void execute() {
System.out.println("执行service...");
}
}
public class IocContainer{
private Map<String,Object> beans = new HashMap<>();
public void registerBean(String name, Object bean){
beans.put(name,bean);
}
public Object getBean(String name){
return beans.get(name);
}
}
public class Client {
private Service service;
public Client(Service service) {
this.service = service;
}
public void doThings(){
service.execute();
}
}
public class Main {
public static void main(String[] args) {
IocContainer container = new IocContainer();
container.registerBean("service",new ServiceImpl());
Client client = new Client((Service)container.getBean("service"));
client.doThings();
}
}
二、什么是DIP(依赖反转)?
依赖反转是面向对象设计原则的一种,它主张高层模块不应该依赖于低层模块,二者都应该依赖于抽象(抽象接口)。而抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。
通过让高层模块不直接依赖于低层模块,而是依赖于抽象接口,这样可以让系统更加灵活,降低模块之间的耦合度,使得代码更加容易维护和扩展。
举例:在下面的例子中FileLogger作为低层模块,Service作为高层模块,Service不是直接去调用FileLogger,而是通过构造函数注入依赖,这样使得高层不直接依赖于低层,而是依赖于抽象的接口。在main函数中通过传入不同的实现类,可以实现输出不同的结果。
public interface Logger{
void log(String message);
}
public class FileLogger implements Logger{
@Override
public void log(String msg){
System.out.println("我是FileLogger "+msg);
}
}
public class DatabaseLogger implements Logger{
@Override
public void log(String msg){
System.out.println("我是DatabaseLogger "+msg);
}
}
public class Service{
private Logger logger;
public Service(Logger logger){
this.logger = logger;
}
public void execute(){
logger.log("日志输出...");
}
}
public static void main(String[] args) {
Service service1 = new Service(new DatabaseLogger());
Service service2 = new Service(new FileLogger());
service1.execute();
Service2.execute();
}
三、什么是DI(依赖注入)?
依赖注入是一种软件设计模式,用于实现依赖反转原则。通过依赖注入能使得对象的依赖关系不再由对象本身的内部创建,而是由外部容器(比如框架或者配置代码)负责创建和注入这些依赖。这种方式有助于降低程序各组件间的耦合度,提高系统的灵活性和可维护性。
实现依赖注入的方式有3种:1、构造函数注入;2、属性注入;3、方法注入。
通过构造函数注入如下:
public class Test{
private Service service;
public Test(Service service){
this.service = service;
}
public void doThings(){
service.execute();
}
}
通过属性注入如下:
public class Test{
@Autowired
private Service service;
public void doThings(){
service.execute();
}
}
通过方法注入如下:
public class Test{
private Service service;
@Autowired
public void setService(Service service){
this.service = service;
}
public void doThings(){
service.execute();
}
}