A deep understanding of the design pattern of javascript
Design Mode
The design pattern is a general design structure that is useful for reusable object-oriented design. Design patterns determine classes and their entities, their roles and collaboration, and their distribution of responsibility.
Each design pattern focuses on an object-oriented design challenge or problem. It describes whether it can be used under other design constraints, the consequences and gains and losses after it is used. Because we must ultimately implement our design patterns, every Design Pattern provides examples and code to illustrate the implementation.
Although design patterns are described as object-oriented designs, they are based on solutions that have been implemented by mainstream object-oriented languages ...".
Type
The design patterns can be divided into several different types. In this part, we will be divided into three types: Creation design patterns, structure design patterns, and behavior design patterns.
Creation Design Mode
The creation design mode focuses on the mechanism and method of object creation. Through this method, objects are created to adapt to the work environment. The basic object creation method may add extra complexity to the project, and the purpose of these modes is to solve this problem by controlling the creation process.
Constructor, Factory, Abstract Factory, Prototype, Singleton) and Builder mode ).
Structure Design Mode
The structure mode focuses on Object composition and common sense to realize the relationship between different objects. This mode does not need to change the entire system structure when a part of the system changes. This mode also helps to reorganize a part of the system that does not reach a certain goal.
The following modes are available in this category: decoration mode, appearance mode, metadata mode, adapter mode, and proxy mode.
Behavior Design Pattern
Behavior patterns focus on improving or streamlining communication between different objects in the system.
The behavior modes include iteration mode, intermediary mode, observer mode, and visitor mode.
Next we will introduce various common design patterns separately to deepen our understanding of the design patterns.
Constructor Mode
The constructor is a special function used to initialize a new object when the memory of the new object is allocated. The object constructor is used to create special types of objects. First, it needs to prepare the objects to be used. Second, when an object is first created, it receives parameters, the constructor is used to assign values to attributes and methods of members.
Because javascript does not support the concept of classes, you must use the new keyword to initialize the object through the constructor. The code for a basic constructor is as follows:
Function Car (model, year, miles) {this. model = model; this. year = year; this. miles = miles; this. toString = function () {return this. model + has done + this. miles + miles ;};}// usage: // We can sample A Carvar civic = new Car (Honda Civic, 2009,200 00); var mondeo = new Car (Ford Mondeo, 2010,500 0); // open the browser console to view the output values of these toString () methods. // output of the toString () method being called on // these objectsconsole. log (civic. toString (); console. log (mondeo. toString ());
In this case, the inheritance is troublesome, and functions such as toString will be redefined in the objects created by each Car constructor. So we still need to use the prototype to achieve the best constructor:
Function Car (model, year, miles) {this. model = model; this. year = year; this. miles = miles;} // Note that we use Note here that we are using Object. prototype. newMethod instead of // Object. prototype to avoid redefining the prototype object Car. prototype. toString = function () {return this. model + has done + this. miles + miles;}; // use: var civic = new Car (Honda Civic, 2009,200 00); var mondeo = new Car (Ford Mondeo, 2010,500 0); console. log (civic. toString (); console. log (mondeo. toString ());
Factory Model
A factory can provide a public interface for object creation, in which we can specify the type of the factory object we want to create. To put it simply, like a water dispenser, whether coffee or milk is needed depends on which button you press.
The simple factory mode can be reflected when creating ajax objects. You can use $. ajax method to understand, can also be understood by a self-written ajax method, address in: http://runjs.cn/code/j5dkikwu
ajax(test002.txt,{type:GET,data:{name:liuf,age:23},onsuccess:function(responseText,xhr){document.getElementById(input).value=responseText;},onfail:function(){//document.write(fail);}});
Ajax is actually a factory method. Whether it is a get or post method is determined by the Code below. This is what we mentioned above: "A factory can provide a public interface for object creation, where we can specify the type of factory object we want to create ".
Singleton Mode
The Singleton mode is called because it limits a class to have only one instantiated object. The classic implementation method is to create a class which contains a method. If no object exists, a new instance object is created. If the object exists, this method only returns the reference of this object. However, javascript is inherently non-class, so simply put, it is created without being used, and directly used without being created.
Let's take a look at the real case. Click a button and a mask layer will appear. This is a common requirement. The Code is as follows:
var createMask = function(){ return document,body.appendChild( document.createElement(div) ); }$( 'button' ).click( function(){ var mask = createMask(); mask.show(); })
In this way, a problem occurs, that is, each call to createMask creates a new div. Although it can be removed when the mask layer is hidden, this will still cause performance loss, the following improvements can be made to create a div at the beginning of the page. The Code is as follows:
var mask = document.body.appendChild( document.createElement( ''div' ) ); $( ''button' ).click( function(){ mask.show(); } )
This ensures that only one mask layer will be created on the page, but there is also a problem, that is, if the user does not need to use this div, It is not created in vain. So we can use a variable to determine whether a div has been created. The Code is as follows:
var mask; var createMask = function(){ if ( mask ) return mask; else{ mask = document,body.appendChild( document.createElement(div) ); return mask; } }
This looks good, but does mask, as a global variable, cause pollution? Therefore, the best method is as follows:
var createMask = function(){ var mask; return function(){ return mask || ( mask = document.body.appendChild( document.createElement('div') ) ) }}()
This is what we mentioned above: "create without it and use it without creating it ". Yes, the singleton mode is so simple that it is not difficult to design the mode. in programming, we have always been useful, but we have not discovered it.
Bridging Mode
The Bridge Mode separates the implementation part from the abstract part so that the two can change independently. When implementing APIs, the bridge mode is very common.
Let's take the javascript forEach method as an example:
forEach = function( ary, fn ){ for ( var i = 0, l = ary.length; i < l; i++ ){ var c = ary[ i ]; if ( fn.call( c, i, c ) === false ){ return false; } }}
As you can see, the forEach function does not care about the specific implementation in fn. the logic in fn will not be affected by the rewriting of the forEach function.
The Code is as follows:
forEach( [1,2,3], function( i, n ){ alert ( n*2 ) } ) forEach( [1,2,3], function( i, n ){ alert ( n*3 ) } )
Appearance Mode
The appearance mode is a ubiquitous mode. The appearance mode provides a high-level interface that allows clients or subsystems to call more methods. For example:
var getName = function(){ return ''svenzeng}var getSex = function(){ return 'man'}
Now I want to call two methods, so I can use a higher-level interface to call:
var getUserInfo = function(){ var info = getName () + getSex (); return info;}
In this way, it is easy to assemble. If you write the two into a function at the beginning, you cannot only call one of them.
Meta Mode
The enjoy mode is a classic structured solution that optimizes repetitive, slow, and inefficient data sharing code. It aims to share as much data as possible with related objects to reduce memory usage in applications (such as application configuration and status ). In general, the metadata mode is used to reduce the number of objects required by the program.
For example, a new div is created every time a waterfall stream in a webpage or a friend list in webqq is pulled down. What if there is a right div? Isn't the browser stuck? So we will think of a way to delete all the divs that have disappeared out of sight, so that the page can maintain a certain number of nodes, but delete and add nodes frequently, it will bring about a lot of performance overhead.
In this case, you can use the metadata mode. The metadata mode provides shared objects for reuse. For example, if only 10 divs can be displayed on the page, the 10 divs that are always displayed in the user's sight can be written as a metadata.
The principle is actually very simple. Put the hidden div into an array. When you need the div, first retrieve it from the array. If there is no more in the array, create another one. the divs in this array are the object meta, and each of them can be used as a carrier of any user information. the Code is as follows:
Var getDiv = (function () {var created = []; var create = function () {return document. body. appendChild (document. createElement ('div ');} var get = function () {if (created. length) {return created. shift () ;}else {return create () ;}/ * a hypothetical event to listen to the div that just disappears out of sight, in fact, you can monitor the scroll bar position to implement */userInfoContainer. disappear (function (div) {created. push (div) ;})} () var div = getDiv (); div. innerHTML =$ {userinfo };
Adapter Mode
The adapter mode converts an interface of a class to another interface that the customer wants. To put it bluntly, there must be a converter, which is an adapter, like an Apple phone that cannot be broken down on a computer chassis.
In the program, the adapter mode is often used to adapt to two interfaces. For example, you are currently using a custom js library. there is a method for getting nodes by id $ id (). one day you think $ implementation in jquery is cooler, but you don't want your engineers to learn new libraries and syntaxes. that adapter will let you do it.
$id = function( id ){ return jQuery( '#' + id )[0]; }
In this way, you do not need to modify them one by one.
Proxy Mode
The proxy mode is to grant access to one object to another Proxy object for operation. To put it bluntly, programmers write daily reports and the daily reports will be reviewed by the Director at the end. However, if everyone sends them directly to the Director, the Director will not be able to work. Therefore, each person will send his/her daily report to his/her team lead and then forward it to the director. This team lead is an agent.
There are also many cases where the proxy mode is used in programming. For example, when a large number of dom operations are performed, we will first create file fragments and then uniformly add them to the dom tree.
Example:
Intermediary Mode
The intermediary mode is the shared object to be observed in the Observer mode. The direct publish/subscribe relationship between objects in the system is sacrificed. Instead, the system maintains a central node for communication. The intermediary mode differs from the proxy mode, as shown in the following figure:
The intermediary object allows each object to be loosely coupled without mutual reference, and can independently change the interaction between transparent objects. In layman's terms, a bank can also be seen as an intermediary between a depositor and a lender. The depositor A does not care who lent his money. Lender B does not care about the deposit he borrowed. The existence of an intermediary makes the transaction so convenient.
Isn't the Controller in the well-known MVC structure an intermediary in programming? Take backbone as an example. the data in a mode is not sure which views are used at the end. the data required by the view can also come from any mode. all binding relationships are determined in controler. the intermediary converts a complex multi-to-many relationship into two relatively simple one-to-many relationships.
The sample code is as follows:
var mode1 = Mode.create(), mode2 = Mode.create();var view1 = View.create(), view2 = View.create();var controler1 = Controler.create( mode1, view1, function(){ view1.el.find( ''div' ).bind( ''click', function(){ this.innerHTML = mode1.find( 'data' ); } )})var controler2 = Controler.create( mode2 view2, function(){ view1.el.find( ''div' ).bind( ''click', function(){ this.innerHTML = mode2.find( 'data' ); } )})
Observer Mode
The observer pattern is such a design pattern. An object called the Observer maintains a group of objects called the observer. These objects depend on the observer, and the observer automatically notifies them of any changes to its own State.
When an observer needs to notify the observer of some changes, it will broadcast, this broadcast may contain some data specific to this notification.
When a specified observer no longer needs to receive notifications from the observer registered by the observer, the observer can delete the notification from the maintained group.
Generally, the interviewer is the observer, while the person waiting for notice is the observer.
Dom events in javascript are actually an embodiment of the observer mode:
div.onclick = function click (){ alert ( ''click' ) }
As long as you subscribe to the div click event, when you click the div, the click function will be executed.
The observer mode can be used to decouple multiple modules. For a multi-person project, I am responsible for Map and Gamer modes:
loadImage( imgAry, function(){ Map.init(); Gamer.init(); } )
Others are responsible for maintaining the loadImage method. If one day I want to add a Sound module, and I have no right to use other people's code, I can only wait for others to come back and add it blank:
loadImage( imgAry, function(){ Map.init(); Gamer.init(); Sount.init(); } )
So we can make the following changes:
loadImage.listen( ''ready', function(){ Map.init(); }) loadImage.listen( ''ready', function(){ Gamer.init(); }) loadImage.listen( ''ready', function(){ Sount.init(); })
After loadImage is complete, you no longer need to care about what will be sent in the future. Next, it only needs to send a signal:
loadImage.trigger( ‘ready’ );
All objects listening for ready events will receive notifications. This is the application scenario of the observer mode.
Speaking of this, the common design patterns are also completed, and a deep understanding of the javascript series will come to an end.