This is the third day of my participation in the August More text Challenge. For details, see: August More Text Challenge

The proxy pattern provides a substitute or placeholder for an object in order to control access to it. The key to the proxy pattern is to provide a surrogate object to control access to an object when it is inconvenient for the client to access it directly or when it is not needed. The client is actually accessing the surrogate object.

The virtual proxy implements image preloading

In Web development, image preloading is a common technique. If you directly set the SRC attribute of an IMG tag, the position of the image is often blank for a period of time due to the large image or poor network. It is common to use a loading placeholder map to load the image asynchronously. Waiting for the image to load and then filling it into the IMG node is a good scenario for using a virtual proxy.

First, create a normal ontology object. This object is responsible for creating an img tag on the page and provides an external setSrc method, which can be called from the outside to set the SRC attribute on the img:

var myImage = (function () {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  return {
    setSrc: function (src) { imgNode.src = src; }}; }) (); myImage.setSrc("http://www.ghostw7.com/uploadslxy/allimg/160125/1T91352B-4.jpg"
);
Copy the code

We can see that on slow Internet connections, there is a long gap in the page before the image loads.

Introduce a proxy object called proxyImage. With this proxy object, a placeholder loading.gif will appear on the page before the image is actually loaded, alerting the user that the image is loading.

var myImage = (function () {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  return {
    setSrc: function (src) { imgNode.src = src; }}; }) ();var proxyImage = (function () {
  var img = new Image();
  img.onload = function () {
    myImage.setSrc(this.src);
  };
  return {
    setSrc: function (src) {
      myImage.setSrc("loading.gif"); img.src = src; }}; }) (); proxyImage.setSrc("http://www.ghostw7.com/uploadslxy/allimg/160125/1T91352B-4.jpg"
);
Copy the code

Currently, MyImage can be accessed indirectly through proxyImage, which controls the customer’s access to MyImage and adds some additional operations to the process, such as before the actual image is loaded, Set img node’s SRC to a loading image.

The meaning of agency

Write an implementation of the preloaded image function without a proxy

var MyImage = (function () {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  var img = new Image();
  img.onload = function () {
    imgNode.src = img.src;
  };
  return {
    setSrc: function (src) {
      imgNode.src = "loading.gif"; img.src = src; }}; }) (); MyImage.setSrc("http://www.ghostw7.com/uploadslxy/allimg/160125/1T91352B-4.jpg"
);
Copy the code

The single responsibility principle: There should be only one reason for a class (and usually objects, functions, etc.) to change.

If an object has more than one responsibility, that means the object is going to be huge, and there may be multiple reasons for it to change, so we need to reduce the coupling.

If you want to remove the code that preloads the image from the MyImage object if the image size is small or if the Internet is fast in the future, you will have to change the MyImage object. That’s where the agency comes in. The agent is responsible for preloading the image, and when the preloading is complete, it redirects the request to the ontology MyImage.

Consistency between broker and ontology interfaces

Having said that, if there comes a day when preloading is not required and the proxy object is not needed, you can choose to request the ontology directly. The key is that both the proxy object and the ontology provide the setSrc method externally, so that the proxy object and ontology are consistent from the user’s point of view. The user does not know the difference between an agent and an ontology, so:

  • The user can safely request the agent and only care about getting the desired result.
  • The use of proxies can be replaced wherever ontology is used.

The caching proxy

Caching proxies can provide temporary storage for expensive operations and return the results of the previous operation if the parameters passed in are the same as the previous one.

Calculation of the product

Create a function that takes the product:

var muti = function () {
  console.log("Let's take the product.");
  var a = 1;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a * arguments[i];
  }
  return a;
};

mult(2.3); / / output: 6
mult(2.3.4); / / output: 24
Copy the code

Now add the cache proxy function:

var proxyMult = (function () {
  var cache = {};
  return function () {
    var args = Array.prototype.join.call(arguments.",");
    if (args in cache) {
      return cache[args];
    }
    return (cache[args] = mult.apply(this.arguments)); }; }) (); proxyMult(1.2.3.4); / / output: 24
proxyMult(1.2.3.4); / / output: 24
Copy the code

When proxyMult(1, 2, 3, 4) is called the second time, the ontology mult function is not evaluated, and proxyMult returns the cached result.

Ajax requests data asynchronously

Projects often encounter paging requirements, the data on the same page theoretically only need to go to the background to pull once, the data that has been pulled need to be cached somewhere, the next request for the same page, can directly use the previous data.

You can also use a caching proxy here. The requested data is an asynchronous operation and needs to be cached in the callback.

Dynamically create proxies with higher-order functions

Create cache proxies for addition, multiplication, subtraction, and so on:

/**************** calculate the product *****************/
var mult = function () {
  var a = 1;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a * arguments[i];
  }
  return a;
};

/**************** calculate the addition and *****************/
var plus = function () {
  var a = 0;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a + arguments[i];
  }
  return a;
};

/**************** Create the cache proxy factory *****************/ 
var createProxyFactory = function (
  fn
) {
  var cache = {};
  return function () {
    var args = Array.prototype.join.call(arguments.",");
    if (args in cache) {
      return cache[args];
    }
    return (cache[args] = fn.apply(this.arguments));
  };
};
var proxyMult = createProxyFactory(mult),
  proxyPlus = createProxyFactory(plus);
alert(proxyMult(1.2.3.4)); / / output: 24
alert(proxyMult(1.2.3.4)); / / output: 24
alert(proxyPlus(1.2.3.4)); / / output: 10
alert(proxyPlus(1.2.3.4)); / / output: 10
Copy the code

Other proxy patterns

  • Firewall proxy: Controls access to network resources and protects topics from “bad guys.”
  • Remote proxy: Provides local representation of an object in different address Spaces.
  • Protection proxy: For situations where objects should have different access permissions.

One last word

If this article is helpful to you, or inspired, please help to like and follow it, your support is the biggest motivation for me to keep writing, thank you for your support.