In simple terms, the key technology is: the Registrar mode.
Scenario Requirements
We know that when writing a class, the class itself has a purpose, there are many methods in the class, and each method does something, and we call this class the main class.
In addition, this main class will rely on some other classes of help, we call these classes as sub-class, in order to achieve the main class target, to rely on a number of classes to match, and the second class is likely to be widely dependent on the main class, such as: Log class.
Programming Ideas
Now let's give an example, I need to use a hookup main class, there is a "gift" method, of course, there are other methods. We only use the "Give gift" method to illustrate.
When we use the type of girls, we only care about the direct method of "send Gifts", and "gift" inside also "choose gifts, Payment," and other operations, as to how to choose gifts, how to pay, it is not my business, these dependent on the sub-class buygift cooperation.
require ' buygift.php '; class hookup{ // send gift function givegift () { $gift New Buygift (); $giftSelect (); $gift,$paoniunew hookup (); $paoniu->givegift ();
Problem at all
So, the starting point of all the problems is to call other sub-classes in a main class, and what we want to solve is the problem that will occur in this class-dependent process.
Well, now you already know what is dependent.
Here's the problem.
Buygift This "sub-class", in addition to girls, can also be placed in the business of this kind of calls, business also to give gifts, of course, can also be applied in other main classes.
If Buygift is called many times and one day needs to change the name, you have to modify it in a number of main classes.
Also, each invocation is instantiated with a new one.
It's not scientific, you know.
What to do? Factory mode
classFactory {Static functionbuygifts () {return Newbuygifts; }}classhookup{ Public functionGivegift () {$this->gift = Factory::Buygift (); $gift-Select (); $gift-Pay (); }} $paoniu=Newhookup ();$paoniu->givegift ();
You see, now the main class hookup to call the sub-class Buygift, you have to find factory class, factory become an intermediary.
Factory The main service of this intermediary is to help you instantiate the sub-class, in addition to manage many times the Class (factory), so you do not have to directly with the sub-class.
This process is called decoupling, no matter how the second class changes, you can find a factory.
But the problem still exists, when we call the factory and its methods in many main classes, but one day we find the factory class to be renamed, or the factory inside the method to rename it? So we're not going to have to change the main class one by one? Although this situation is not many, but this kind of non-credibility of the "black intermediary" also occasionally appears.
What do we do? We also have to prevent this factory intermediary.
Dependency Injection
classFactory {Static functionbuygifts () {return Newbuygifts; }}classhookup{Private $gift; Public functionGivegift () {$this->gift->Select (); $this->gift->Pay (); } Public functionSetgift ($instance){ $this->gift =$instance;}}$paoniu=Newhookup ();$paoniu->setgift (Factory::buygifts ());//see that factory has rolled out our main class.$paoniu->givegift ();
Now hookup class like a company, as the boss you only care about how to pick up girls, dirty live dirty to others to do, so you set up a Setgift procurement department, this department is specialized in dealing with factory intermediary, so factory intermediary completely roll your vision.
Factory this dependent object is instantiated from a static property that is injected externally into the class content by parameters, which is dependency injection.
Can clever you immediately find, I wipe, setgift you this department is responsible for purchasing gift AH? Do I have to setphone,setinvitation to call and make an appointment?
So the main class to write a lot of set method, outside to call many times set method, you will find, more unscientific.
How about we get a "total generation"?
classFactory {Static functionbuygifts () {return Newbuygifts; }}classTopfactory { Public Static functionAll_agents_in_one () {$paoniu _agent=Newhookup (); $paoniu _agent->setgift (Factory::buygifts ()); $paoniu _agent->setphone (Factory::Getphone ()); $paoniu _agent->setinvitation (Factory::sendinvitation ()); return $paoniu _agent; }}classhookup{Private $gift; Public functionGivegift () {$this->gift->Select (); $this->gift->Pay (); } Public functionSetgift ($instance){ $this->gift =$instance;}}$paoniu= Topfactory::All_agents_in_one ();$paoniu->givegift ();
Smart we continue to see clearly, although more than a topfactory to help us deal with a number of set problems, but each main class is also equipped with a general class topfactory, which is also a lot of work, need a more advanced program, so that the programmer's life easier some.
IOC container
This scheme is the IOC container, the IOC container is first a class registrar, and secondly it is a more advanced dependency injection method.
It and the factory factory in fact the same nature, are intermediary agents, but the implementation mechanism is different.
The Factory factory registers the secondary class one by one with the instantiated static method in the class;
The IOC container is a static array in which the sub-class instantiation object is registered to a class in turn;
The design pattern of the IOC container is called the Registrar mode ;
//register all classes with the factoryclassFactory {Static functionbuygifts () {return Newbuygifts (); } Static functionhookup () {return Newhookup (); } Static functionDi () {return NewDi (); }}//the Global container classclassDi {protected $binds; protected $instances; Public functionBind$key,$concrete) { if($concreteinstanceof Closure) { $this->binds[$key] =$concrete; } Else { $this->instances[$key] =$concrete; } } Public functionMake$key,$parameters= []) { if(isset($this->instances[$key])) { return $this->instances[$key]; } Array_unshift($parameters,$this); return Call_user_func_array($this->binds[$key],$parameters); }}//Main classclasshookup{ Public functionGivegift ($gift){ $gift-Select (); $gift-Pay (); }}/ * Initialize each resource start * /
$di = Factory::D i ();
Binding Secondary class
$di->bind (' Buygift ',function(){ returnFactory::buygift ();});//binding the main class to the container$di->bind (' hookup ',function(){ returnFactory::hookup ();});
/ * Initialize each resource complete * /
Get an instance of the main class
$paoniu=$di->make (' hookup ');//get an instance of a secondary class$gift=$di->make (' Buygift ');$paoniu->givegifts ($gift);
// Note that when we bind the IOC container, it is written like this: $di function () { return Factory::buygift ();} // instead of writing this: $di->bind (' Buygift ', Factory::buygift ()); // The first parameter is the key name of the array, and the second parameter is the value of the array;//A callback function is used to read the value of the array, and the second method is instantiated directly into an object and saved to the value of the array. The second method compares the resources.
We are bound to aliases, so the binding class name changes will not affect the use of the main class, only need to modify the class binding code or even only modify the factory class code
1, we have all the class registered to the factory factory, so that we do not need trouble new.
2. We bind all classes to the Container di instead of instantiating it, and when we call the Make method of Di, we instantiate the operation.
So, for the framework, when we initialize, we can do 1 and 2 of the operation, which does not occupy much resources, because there is no instantiation, but only the binding and registration of the operation, equivalent to configure the mapping.
And only when we need to use these classes, do we do the $di->make () operation and return an instance of the class. At this point, our entire framework of the class resources can be called without new or introduced, and do not worry about resource consumption, greatly improve the development flexibility and reduce the coupling of the program.
Detailed Dependency Injection (DI) and IOC container