Learn JavaScript Design patterns (interfaces) _javascript tips

Source: Internet
Author: User
Tags function definition getdate

1, interface overview

1), what is the interface?

Interfaces provide a means of describing what methods an object should have. Although it can indicate the semantics of these methods, it does not specify how these methods should be implemented.

2), the benefit of the interface

    • Facilitates the reuse of code.

An interface can tell a programmer what methods a class implements to help it use this class.

    • Helps stabilize the way of communication before the same kind.
    • Tests and modes can therefore become easier.

In a weakly typed language such as JavaScript, type mismatch errors are difficult to track. Using an interface makes it easier to find this error, because at this point, if an object does not resemble the type required, or does not implement the necessary methods, you will get a clear error message that contains useful information. As a result, logical errors can be limited to the method itself, not to the composition of the object.

    • Interfaces can also make your code more secure.

Because any change to the interface must be reflected in all classes that implement it. If an interface adds an action, and a class that implements it does not add the action accordingly, you will surely see an error immediately.

3), the disadvantages of the interface

JavaScript is a language with strong expressive pictures, which mainly benefits from its weak type. And the use of the interface is a certain program to enhance the role of the type. This reduces the flexibility of the language. JavaScript does not provide built-in support for interfaces, and attempts to emulate features built into other languages always have some risks.

The biggest problem with the interface in JS is that you can't force other programmers to follow your defined interface. In other languages, the concept of an interface is built-in, and if someone defines a class that implements an interface, the compiler will ensure that the class does implement the interface. In JavaScript, however, it is necessary to use manual methods to ensure that a class implements an interface. Coding Specifications and helper classes can provide some help, but this problem cannot be completely eradicated. If the other programmers of the project do not take the interface seriously, the use of these interfaces is not guaranteed to be mandatory. Unless everyone in the project agrees to use the interface and check it, many of the values of the interface are not reflected.

2. Imitate the interface in JavaScript

Three methods of imitating interface in javascript: annotation description method, attribute check method, duck type discrimination method.

None of the techniques are perfect, but the combination of the three can be basically satisfying.

1), the annotation description method implements the interface

Using annotations to mimic an interface is the easiest way, but the effect is the worst. This method mimics the practices in other Page object languages, using the interface and implements keywords, but placing them in comments so as not to cause grammatical errors. As follows:

There are three ways to define interfaces in JavaScript:
//1, the way annotations are described

 /**  
  * Interface composite{
* function Add (obj);
* Function remove (obj);
* Function update (obj);
}

Advantages: Programmers can have reference
shortcomings: A lot of shortcomings, he is just an excuse for the document category, if not implement
   all the methods, the program can still run, too loose. Hard to test and debug

//Implement of Interface composite
var Compositeimpl =function () {

 /*this.add = function (obj) {

  };
  This.remove = function (obj) {

  };
   This method of function definition, when instantiating an object,
   a new example will produce a method, and the methods of each strength are different.
   so use the following method:
  */
  CompositeImpl.prototype.add = function (obj) {

  }
  CompositeImpl.prototype.remove = function (obj) {

  }    
  CompositeImpl.prototype.update = function (obj) {
  }
}

var C1 = new Compositeimpl ();
var C2 = new Compositeimpl ()

alert (C1.add = = C2.add)

This imitation is not very good. It does not check to make sure that composite really implements the correct set of methods, nor does it throw an error to inform the programmer of the problem in the program. In the final analysis it mainly belongs to the scope of the program document. In this practice, the adherence to the interface agreement is entirely dependent on consciousness.

2), attribute detection method to implement the interface

This approach is a bit more rigorous. All classes explicitly declare which interfaces they implement, and those that want to deal with those classes might check for those claims. The interfaces themselves are still just annotations, but now you can check a property to see what kind of interface the class claims to implement.

/** * Interface composite{* function add (obj);
 * Function remove (obj);
 * Function update (obj);
 *} * Interface formitem{* Function select (obj); *///Compositeimpl Implements interface Composite,formitem var Compositeimpl =function () {//displayed within the class, receiving the implemented
    Port, generally speaking, this is a specification,//We project manager: Define an array in the inner class, name to be fixed this.interfaceimplments = [' composite ', ' formitem '];
  CompositeImpl.prototype.add = function (obj) {alert ("pinky"); } CompositeImpl.prototype.remove = function (obj) {} CompositeImpl.prototype.update = function (obj) {}/*co MpositeImpl.prototype.select = function (obj) {}*/}//define functions detection to determine whether the current object implements all interface function Checkcompositeimpl (Insta NCE) {if (!isimplments (instance, ' composite ', ' Formitem ')) {throw new Error (' Object cannot implements all int
    Erface ');
  }; }//Public specific detection method (core method), the main purpose is to determine whether the sample object has implemented the relevant interface, function isimplments (object) {//arguments object will be the actual object of the objects for (var i = 1, len = arguments.length; I < Len;
      i++) {//note here starting from 1, one way to judge.      var InterfaceName = arguments[i]; Receive the name of the implementation of each interface var interfacefound = false;//To determine whether this method is implemented or failed?

      Interfaceimplments is defined in the specification.
          for (var j = 0;j < Object.interfaceImplments.length j + +) {if (object.interfaceimplments[j] = = InterfaceName) {
          Interfacefound = true;
        Break
       }
      };
       If not implemented, returns False if (!interfacefound) {return false;

    };
  return true;
var C1 = new Compositeimpl ();

Checkcompositeimpl (C1);

 C1.add ();

In this example, Compositeimpl claims to have implemented the composite interface by adding the two interface names to an array named Implementsinterfaces. Class to explicitly declare what interfaces they support. Any function that requires a parameter to be of a particular type can check this property and throw an error if the required interface is not in the declared column.

This method has several advantages. It provides a documentation description of the interfaces that the class implements. If the interface you want is not in the list of interfaces that a class claims to support, you will see an error message. By exploiting these errors, you can force other programmers to declare these interfaces.

The main disadvantage of this approach is that it does not ensure that the class actually implements the interface that it claims to implement. You only know if it says that it implements the interface. It is common to declare that a class implements an interface when it is created, but it then misses one of the methods it implements in the interface. At this point all of the checks can pass, but that method does not exist, which will be buried in the code a hidden danger. It also requires some extra work to explicitly declare interfaces supported by the class.

3), duck-type discrimination method to implement the interface

In fact, it doesn't matter whether a class declares which interfaces it supports, as long as it has the methods in those interfaces. Duck type (the name comes from James Whitomb Riley's famous quote: "Walk like a duck and quack a duck") is based on this understanding. It takes the set of methods implemented by an object as the sole criterion for determining whether it is an instance of a class. This technique can also show great skill when checking whether a class implements an interface. The idea behind this approach is simple: If an object has all methods with the same name as the method defined by the interface, it can be considered to implement this interface. You can use an auxiliary function to make sure that the object has all the necessary methods:

/* The third way to implement the interface: Duck type Hair interface, (more perfect method) Core idea: a class to implement the main purpose of the interface: The method is implemented (detection method) fully object-oriented code to achieve unity, decoupling///1, Interface class---class Interf Ace ===> Instantiate n multiple Interfaces/** * Interface class parameters?  Several * parameter 1: Interface name * Parameter 2: Receive method Set (array)/var Interface = function (name, methods) {//To determine the number of parameters of an interface if (Arguments.length!=2)
   {throw new Error (' The instance interface constructor arguments should be 2 ');
   };
   THIS.name =name;
   This.methods = methods;
   This.methods = []; for (var i = 0, len = methods.length i <len; i++) {if (typeof Methods[i]!== "string") {throw new Error (
     ' The name of ' is wrong ');
   } this.methods.push (Methods[i]);
}//2, preparatory work, specific implementation//(1) Instantiate interface object var compositeinterface = new Interface (' Compositeinterface ', [' Add ', ' delete ']);


 var formiteminterface = new Interface (' Formiteminterface ', [' Update ', ' select ']); (2) The specific implementation class//compositeimpl implments Compositioniterface formitemiterface var compositeimpl = function () {}//(3) implements the interface's Methods Implements methods Compositeimpl.prOtotype.add = function (obj) {alert ("Add");}     
CompositeImpl.prototype.delete = function (obj) {alert ("delete");} CompositeImpl.prototype.update = function (obj) {alert ("Update");}/*compositeimpl.prototype.select = function (obj) {A
Lert ("select");
}*///3, verify the method in the interface//if the test passes, does not do anything, does not pass, throws an exception. The purpose of this method is to detect the Interface.ensureimplements =function (object) {//If the accepted parameter length is less than 2, proving that there is any interface that implements the IF (arguments.length ;
   2) {throw new Error (' The Interface has no implement class ');

   };
     Gets the instance object for the interface for (var i = 1, len= arguments.length i < len; i++) {var instanceinterface =arguments[i];  Determines whether the parameter is the type of the interface class if (Instanceinterface.constructor!==interface) {throw new Error (' The arguments constructor
     is not Interface Class ');

     };
        for (var j = 0, Len2 =instanceinterface.methods.length J <len2; J) {//with a temporary variable, receive the name of each method (note for string type)
        var methodname = Instanceinterface.methods[j]; Object[key] Gets the method if (!oBject[methodname] | |
        typeof Object[methodname]!== ' function ') {throw new Error (' The method ' ' + methodname+ ' ' are not found ');
var C1 =new Compositeimpl ()}}};
Interface.ensureimplements (C1,compositeinterface,formiteminterface);

 C1.add ();

Unlike the other two methods, this method does not use annotations. All aspects of it can be enforced. The Ensureimplements function requires at least two parameters. The first parameter is the object you want to check. The remaining parameters are the interfaces that are used to check that object. This function checks whether the object represented by its first argument implements all the methods declared by those interfaces. If any of the methods are missing, it throws an error that contains useful information such as the missing method and the name of the interface that was not implemented correctly. This check can be used in code where you need to ensure that an object implements an interface. In this case, the AddForm function does not add to a form object until it supports all the necessary methods.

Although duck type identification may be the most useful of the three methods mentioned above, it also has some drawbacks. In this approach, the class does not declare which interfaces it implements, which reduces the reusability of the code and lacks the self-describing nature of the other two methods. It needs to use a helper class interface and an auxiliary function ensureimplements. Also, it only cares about the name of the method, and does not check the name, number, or type of its arguments.

3, the use of interface type of occasions

Strict type checking is not always advisable. Many JS programmers do not use the interface or the kind of inspection it provides, but also dry for many years. Interface can best embody its value when using design pattern to implement complex system. It seems to reduce the flexibility of JavaScript, but in fact, it increases the flexibility of the code because it lowers the coupling between objects. An interface can make a function more flexible, because you can pass any type of argument to a function and make sure that it uses only those objects that have the necessary methods.

4, the use of interface class

The most important step is to determine whether using an interface in your code is cost-effective. For small, less-expensive projects, the benefits of interfaces may not be obvious, but only to increase their complexity. You need to weigh the pros and cons yourself. If you think that the use of interfaces in a project is more than a disadvantage, you can use the following instructions:
1), the interface class into the HTML file.
2), check all the code in the object as the parameters of the method. What are the methods of these object parameters that are required for the normal operation of the code
3 Create a interface object for each of the different sets of methods you need.
4), remove all explicit checks for the constructor. Because we use duck-type discrimination, the type of object is no longer important.
5), replace the original builder check with Interface.ensureimplements.

Example
Suppose you want to create a class that converts some automated test results into a format that is appropriate for viewing on a Web page. The constructor of the class takes an instance of a TestResult class as a parameter. It formats and outputs the data encapsulated by the TestResult object at the request of the customer.
Original definition:

 var resultformatter =function (Resultsobject) {if (!) ( Resultsobject instanceof TestResult)) {throw NewError ("Resultsformatter:constructor requires an instance of Testresu
    Lt Asan argument. ")}
  This.resultsobject = Resultsobject;
    } ResultFormatter.prototype.renderResults =function () {var dateoftest = this.resultsObject.getDate ();
    var resultsarray =this.resultsobject.getresults ();
    var resultscontainer =document.createelement (' div ');
    var resultsheader =document.createelement ("H3");
    resultsheader.innerhtml = "TestResults from" +dateoftest.toutcstring ();
    Resultscontainer.appendchild (Resultsheader);
    var resultlist =document.createelement ("ul");
    Resultscontainer.appendchild (resultlist);
      for (Var i=0,len=resultsarray.length;i<len;i++) {var listitem=document.createelement (' Li ');
      Listitem.innerhtml =resultsarray[i];
    Resultlist.appendchild (ListItem);
  return resultscontainer; }

The constructor of the class checks the parameter to ensure that it is indeed an instance of the TestResult class. If the argument does not reach the, the constructor throws an error. With this assurance, when writing the Renderresults method, you can assume that there are both getdate and getresults to use. In fact, this does not guarantee that the required methods have been implemented. The TestResult class may be modified so that it no longer owns the GETDATE () method. In this case, the check in the constructor still passes, but the Renderresults method fails.

In addition, this check of the constructor imposes some unnecessary restrictions. It does not allow instances of other classes to be used as arguments, even if they are intended to work. For example, there is a method named Weatherdata that also owns both GetDate and GetResults. It could have been used properly by the Resultformatter class. But that explicit type check blocks any instance of the Weatherdata class from being used.
The problem-solving approach is to remove the check that uses instanceof and replace it with an interface. First, we need to create this interface:

Resultsetinterface.
var ResultSet =new Interface ("ResultSet", [' getDate ', ' getresults ']);

This line of code above creates a new instance of the interface object. The first argument is the name of the interface, and the second argument is an array of strings, each of which is a required method name. With this interface, you can use an interface check to replace the instanceof check

var resultformatter = function (resultsobject) {
 interface.ensureimplements (resultsobject,resultset);
 This.resultsobject = Resultsobject;
}
resultformatter.prototype.renderresults= function () {
 ...
}

The Renderresults method remains unchanged. Instead, the constructor is changed to use the Ensureimplements method instead of the instanceof operator. The constructor can now accept instances of Weatherdata or any other class that implements the desired method. We have only modified a few lines of Resultformatter class code to make that check more accurate and more tolerant.

5. Interface-dependent Design patterns

    • Factory mode
    • Combination mode
    • Decoration mode
    • Command mode

The above is the JavaScript design pattern interface in the implementation of the relevant introduction, I hope to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.