1. Reliance
Dependency is a connection, there is a place to use it is to rely on it, a system can not completely avoid dependence. If one of your classes or modules is not used in the project, congratulations, you can remove it from the project or exclude it, because there is no place to rely on it. Let's look at a simple example:
<summary>/// Users play media files/// </summary> public class Operationmain {
public void PlayMedia () { MediaFile _mtype = new MediaFile (); Player _player = new player (); _player. Play (_mtype); } } <summary> ///player///</summary> public class player {public void play ( MediaFile file) { Console.WriteLine (file. FilePath); } } <summary>///media File/// </summary> public class MediaFile {public string FilePath {get; set;} }
Above is a simple example of a user playing a file with a player, user action is the PlayMedia method in the Operationmain class, open a player, select a file to play. First look at the dependencies between them, you can simply find there are 3 dependencies
- Player Dependent MediaFile
- Operationmain relies on the player
- Operationmain Dependent MediaFile
2. Dependency inversion
The demand has increased, to use different players, play different files, we have to abstract out, reduce coupling.
The coupling relationship is the dependency relationship, if the dependence is very complicated, reaching, difficult to maintain, the less the dependence, the lower the coupling relationship, the more stable the system, so we need to reduce dependence.
Fortunately, Robert Martin Master proposed the principle of object-oriented design----dependency inversion:
- A. The upper modules should not be dependent on the underlying modules, which collectively rely on an abstraction.
- B. Abstractions cannot depend on the image, and the image relies on abstraction.
Understanding: A. The upper layer is the user, the lower layer is the user, which results in the upper layer dependent on the lower level, the underlying changes, will naturally affect the upper layer, resulting in system instability, even reaching. So how to reduce dependence? Is that the upper and lower layers are dependent on another abstraction, this abstraction is relatively stable, the whole is more stable.
B. Object-oriented programming for the abstract or for the pretext of programming, abstract generally more stable, to achieve the specific abstraction is to rely on abstract, abstract should not be dependent on other specific, should rely on abstraction.
In the example above, we have found the dependency, and now we are going to optimize it according to the dependency inversion principle.
Change according to the following principles:
- The player relies on mediafile, so that both player and MediaFile rely on an abstraction imediafile
- Operationmain relies on the player to make Operationmain and player dependent on an abstract iplayer
- Operationmain relies on mediafile, so that Operationmain and mediafile all rely on an abstract imediafile
- iplayer can not rely on specific mediafile, should rely on the specific mediafile of the abstract imediafile
The structure is simple, so the code is roughly the following:
<summary>/// Users play media files/// </summary> public class Operationmain {
public void PlayMedia () { Imediafile _mtype = new MediaFile (); IPlayer _player = new player (); _player. Play (_mtype); } } <summary> ///player////</summary> public interface IPlayer {void Play ( Imediafile file); } <summary>///default player/// </summary> public class Player:iplayer { public void Play (imediafile file) { Console.WriteLine (file. FilePath); } } <summary>///media File/// </summary> public interface imediafile { string FilePath {get; set;} } <summary>/// Default media File/// </summary> public class Mediafile:imediafile { public string FilePath {get; set;} }
The above code is abstracted, it can be seen that the purpose is to reduce the dependency, but it seems that the dependency increased, such as the user PlayMedia method, the dependency also increased the dependency interface and the specific implementation, but the interface is stable, can not be considered, the specific implementation is the change, this depends on it, to play the file, Must use specific players and specific files.
3. Control reversal (IoC)
Real life, is the specific player and the specific media file does not matter, you give it a Mp3 file He can play, give it a MP4 file It can also play, you delete your media files, the player is still in, specific what player, play what file, control all of our users themselves.
The above example is basically isolated, the specific player with the specific media isolation, the specific player only with the media interface and player interface. But PlayMedia method inside the specific object, write dead, control is very small, if I want to use Baidu audio and video playback, I want to change a music, can only re-change the code, that control how to transfer it?
We can create by reflection, the specific file name written in the configuration file, the client code is not changed, only need to change the configuration file, stability has improved, as follows:
public void PlayMedia () { Imediafile _mtype = Assembly.Load (configurationmanager.appsettings["Assemname"]). CreateInstance (configurationmanager.appsettings["MediaName"]); IPlayer _player = Assembly.Load (configurationmanager.appsettings["Assemname"]). CreateInstance (configurationmanager.appsettings["playername"]); _player. Play (_mtype); }
This object is the one that is fully controlled by the configuration file, the control of the specific object to the configuration file, which is often said to control inversion.
The control reversal IOC is the abbreviation for inversion of control, which is to say that the object is transferred, transferred to a third party, such as transferred to the IOC container, it is a creation factory, you want what object, it gives you what object, with the IOC container, the dependency is changed, The original dependencies were gone, and they all relied on the IOC container to establish their relationship through the IOC container.
4. Dependency Injection (DI)
The above mentioned control inversion, is a concept, but also to achieve specific, the above configuration file is also a way of implementation. The concrete thought is put forward by the dependency injection.
The dependency injection di is the dependency injection abbreviation, which raises the "What kind of control has been reversed and has been shifted?" ", it also gives the answer:" The creation of dependent objects is reversed. "
The so-called dependency injection is that the IOC container dynamically injects some kind of dependency into the object during operation.
In the example above, which to rely on injection, dependent objects need to get an instance of the place, namely the PlayMedia method, need to iplayer specific objects and imediafile specific objects, find a place to start from here, in order to control these two objects flexibly, Must be outside to be able to control the instantiation of two objects, to provide external operations is necessary, can be a property, can be a method, can be a constructor, in short, you can control it elsewhere, the following will be injected using unity, using the constructor injection, the code is as follows:
<summary>///Users Play media files///</summary> public class Operationmain {Imediafile _mtyp E IPlayer _player; Public Operationmain (IPlayer player, Imediafile mtype) {_player = player; _mtype = Mtype; } public void PlayMedia () {_player. Play (_mtype); }}///<summary>///player////</summary> public interface IPlayer {void Play (IMEDIAF ile file); }///<summary>///default player///</summary> public class Player:iplayer {public void Pla Y (imediafile file) {Console.WriteLine (file. FilePath); }}///<summary>//media File///</summary> public interface Imediafile {string Filepa th {get; set;} }///<summary>///default media File///</summary> public class Mediafile:imediafile {public S Tring FilePath {get; set;} }
Give the Operationmain Class A constructor because unity has a constructor injection and the calling code is as follows:
Static UnityContainer container = new UnityContainer (); static void Init () { container. Registertype<iplayer, player> (); Container. Registertype<imediafile, mediafile> (); } static void Main (string[] args) { init (); Operationmain OP1 = container. Resolve<operationmain> (); Op1. PlayMedia (); Operationmain OP3 = container. Resolve<operationmain> (); Op3. PlayMedia (); Normal mode operationmain OP2 = new Operationmain (new Player (), New MediaFile ()); Op2. PlayMedia (); Console.read (); }
Let's see, unity has more than that, you can initialize it with more than N, use it directly later, instead of using new, there's a flexible control of the instance cycle control, configuration files, and so on, you can see the description of unity (not specifically in this section).
IOC mode (dependency, dependency inversion, Dependency injection, control inversion)