PHP control inversion (IOC) and dependency injection (DI), iocdi
Let's take a look at an example:
<?phpclass 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(){//TODOecho 'b';}}class C{public function C(){//TODO}public function Method(){//TODOecho 'c';}}$a=new A();$a->Method();?>
The above code makes it easy to understand one sentence:
ClassDependencyClass B and class C
That is to say, if you need to modify Class B or Class C during future development, once the function is renamed, the number of function parameters changes, or even the adjustment of the entire class structure, we also need to make corresponding adjustments to Class A, and the independence of Class A is lost, which is inconvenient in the development process, that is, what we say is "taking A whole body ", if two classes are written separately by two people, conflicts often arise at this time...
If you really want to change class B and class C, is there A way to change the Class A code as little as possible? Control inversion is used here.
The high-level module should not depend on the underlying module, and both should depend on abstraction.
IOC is an idea, and dependency injection (DI) is a method to implement this idea.
The first method is constructor injection (this method is not recommended, but better than not)
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();} }
Write the client class as follows:
$a=new A(new B(),new C());$a->Method();
The constructor of Class A depends on class B and class C. It passes in through the constructor parameters and implements at least one point, that is, class B and class C objects are created outside class A. Once class B and class c are modified, Class A does not need to be modified, you only need to change it in the client class.
Assume that one day, we need to expand Class B and create two subclasses of Class B.
class B{public function B(){//TODO}public function Method(){//TODOecho '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 is also very simple. The client class is written as follows:
$a=new A(new B2(),new C());$a->Method();
Therefore, Class A does not need to care about the subclasses of class B. You only need to care about them on the client.
The second method is 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;}}}}
Change the Class A code:
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 constructor of class B and class C changes, such as modifying function parameters, we only need to change the Factory class.
Abstraction should not depend on details, but on abstraction.
Abstract The methods in class B and class C and create an interface.
interface IMethod{public function Method();}
In this way, the $ B and $ c variables in Class A are no longer specific variables, but abstract variables, I don't know how their Method is implemented.
class B implements IMethod{public function B(){//TODO}public function Method(){//TODOecho 'b';}}class C implements IMethod{public function C(){//TODO}public function Method(){//TODOecho 'c';}}
Summary:
1. We will move the creation of class B and class C objects in Class A out of class.
2. Originally, Class A was dependent on class B and class C, and now A is dependent on Factory, Factory is dependent on class B and class C.