Home>

Recently using thinkphp5 framework, I looked at his source code,I found that dependency injection (inversion of control) is also used in many places. I think it is necessary to briefly talk with you about what is dependency injection and how to use it.

First look at an example:

<?php
class a
{
public $b;
public $c;
public function a ()
{
//todo
}
public function method ()
{
$this->b=new b ();
$this->c=new c ();
$this->b->method ();
$this->c->method ();
//todo
}
}
class b
{
public function b ()
{
//todo
}
public function method ()
{
//todo
echo "b";
}
}
class c
{
public function c ()
{
//todo
}
public function method ()
{
//todo
echo "c";
}
}
$a=new a ();
$a->method ();
?>

The above code,We can easily understand a sentence:

Class a depends on classes b and c

That is,If in the future development process,To modify class b or c, once the function is renamed,The number of function parameters changes,Even the adjustment of the entire class structure,We also need to make corresponding adjustments to category a,type a independence is lost,This is very inconvenient during the development process,It ’s what we mean by "leaving the whole body". If two classes are written by two people,Contradictions often arise at this time.. .

In case there is really a need to change classes b and c, is there a way to do it,Can you not change or minimize the code of class A?Control inversion is used here.

High-level modules should not depend on lower-level modules,Both should rely on abstraction.

Inversion of control (ioc) is an idea,Dependency injection (di) is the way to implement this idea.

The first method is called:constructor injection (this method is also not recommended,But better than nothing)

class a
{
public $b;
public $c;
public function a ($b, $c)
{
$this->b=$b;
$this->c=$c;
}
public function method ()
{
$this->b->method ();
$this->c->method ();
}
}

The client class is written like this:

$a=new a (new b (), new c ());
$a->method ();

The constructor of class a depends on classes b and c. It is passed in as a parameter to the constructor.At least a little bit is achieved,That is, the creation of class b objects b and c class objects c have been moved outside of class a, so once class b and c are changed,Class a does not need to be modified,Just change it in the client class.

If one day,We need to extend class b and make two subclasses of class b

class b
{
public function b ()
{
//todo
}
public function method ()
{
//todo
echo "b";
}
}
class b1 extends b
{
public function b1 ()
{
//todo
}
public function method ()
{
echo "b1";
}
}
class b2 extends b
{
public function b2 ()
{
//todo
}
public function method ()
{
echo "b2";
}
}

It's also very simple,The client class is written like this:

$a=new a (new b2 (), new c ());
$a->method ();

So class a doesn't need to care about which subclasses of class b.Just care about the client class.

The second method is called:factory mode injection (recommended)

class factory
{
public function factory ()
{
//todo
}
public function create ($s)
{
switch ($s)
{
case "b":
{
return new b ();
break;
}
case "c":
{
return new c ();
break;
}
default:
{
return null;
break;
}
}
}
}

Our class A code is changed to:

class a
{
public $b;
public $c;
public function a ()
{
//todo
}
public function method ()
{
$f=new factory ();
$this->b=$f->create ("b");
$this->c=$f->create ("c");
$this->b->method ();
$this->c->method ();
//todo
}
}

In fact, a small part has been decoupled,At least if the constructors of classes b and c change,Such as modifying function parameters,We just need to change the factory class.

Abstraction should not depend on details,Details should depend on abstraction.

Abstract the methods in classes b and c,Make an interface

interface imethod
{
public function method ();
}

In this way, the $b and $c variables in class a are no longer a specific variable.But an abstract type variable,Before the moment of running,I don't know how their method is implemented.

class b implements imethod
{
public function b ()
{
//todo
}
public function method ()
{
//todo
echo "b";
}
}
class c implements imethod
{
public function c ()
{
//todo
}
public function method ()
{
//todo
echo "c";
}
}

A few points:

1. We move the creation of class b objects and class c objects in class a out of class a

2. Originally class a depended on classes b and c, but now it becomes a dependency on factory and factory depends on b and c.

php
  • Previous Angular2 router routing navigate use and refresh the page in detail
  • Next Java implements TCP server through Socket