This is the 20th day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

What is IoC and what are its application scenarios

Inversion of Control (IoC) is a design principle that, as the name implies, inverts various controls in object-oriented design to reduce the coupling of code and make programs modular and easy to expand. IOC means handing over the management of both dependent and dependent modules to the container, which dynamically injects its dependencies into the module as we use it. To solve the above problems, IoC mode is often needed, and DI(Dependency Injection) is generally used to achieve it

// The ordered class is an example. Let's look at the case without dependency injection:
// The Order model class models/ order.js
class Order {
    constructor() {}
    insert() {
        / /... Some database operations
        return true; }}/ / order controllers/OrderController. Js

const Order = require("./Order.js");

class OrderController {
    constructor() {
        this.order = new Order();
    }
    createOrder(. args) {
        this.order.insert(...args);
    }
}

// router/index.js
const OrderController = require(".. /controllers/OrderController.js");
const orderController = new OrderController();
Copy the code

The OrderController class is coupled to the Order class and must require the Order class before it can be used. If the Order class has a change number, then all files that depend on the Order class need to be changed. Take a look at dependency injection:

// The Order model class models/ order.js
class Order {
    constructor() {}
    insert() {
        / /... Some database operations
        return true; }}/ / order controllers/OrderController. Js
class OrderController {
    constructor(order) {
        this.order = new order();
    }
    craeteOrder(. args) {
        this.order.insert(...args);
    }
}

//router/index.js
const Order = require(".. /models/Order.js");
const OrderController = require(".. /controllers/OrderController.js");
const orderController = new OrderController(new Order());

Copy the code

You can see dependency injection and module decoupling, but there are still shortcomings. The advantages and disadvantages of dependency injection are summarized as follows: Advantages: Through dependency injection, the coupling degree between the high-level module and the low-level module is reduced. Therefore, when the low-level module changes, we do not need to understand the changes of the low-level module, but only need to manage the dependent paths of the Router. Cons: All of our dependent modules are imported into the Router, which significantly increases the complexity of the Router module. We need an easy way to manage both the injected and the injected. This is what we call the IoC container

class IOC {
    constructor() {
        this.controller = new Map(a); }bind(key, callback) {
        this.controller.set(key, {
            callback,
            single: false
        });
    }
    sigleton(key, callback) {
        this.controller.set(key, {
            callback,
            single: true
        });
    }
    use(key) {
        const item = this.controller.get(key);
        if(! item) {throw new Error("error");
        }
        if(item.single && ! item.instance) { item.instance = item.callback(); }returnitem.single ? item.instance : item.callback(); }}//router/index.js
const Order = require(".. /models/Order.js");
const OrderController = require(".. /controllers/OrderController.js");
ioc.bind("order".(. args) = > new OrderController(newOrder(... args)));// router.js
const ioc = require(".. /ioc.js");
const orderController = ioc.use("order");
Copy the code

This is a simple Ioc container implementation that binds dependencies between modules to the container using the bind method. Use method to determine whether the module exists, if not, an error will be reported; Callback() does not need to be executed if it exists.