Heim > Web-Frontend > js-Tutorial > Anwendung des Adapters in JavaScript (mit Beispielen)

Anwendung des Adapters in JavaScript (mit Beispielen)

不言
Freigeben: 2018-09-19 15:08:40
Original
1588 Leute haben es durchsucht

Der Inhalt dieses Artikels befasst sich mit der Anwendung von Adaptern in JavaScript (mit Beispielen). Freunde in Not können darauf verweisen.

Das Adapterentwurfsmuster ist in JavaScript sehr nützlich. Es zeigt sich bei der Bewältigung von browserübergreifenden Kompatibilitätsproblemen und der Integration von Aufrufen mehrerer SDKs von Drittanbietern.
Tatsächlich schreiben wir in der täglichen Entwicklung oft versehentlich Code, der einem bestimmten Entwurfsmuster entspricht. Schließlich handelt es sich bei Entwurfsmustern um einige von Senioren zusammengefasste und verfeinerte Vorlagen, die zur Verbesserung der Entwicklungseffizienz beitragen können .
Tatsächlich sollten Adapter in JavaScript relativ häufig vorkommen.

In Wikipedia lautet die Definition des Adaptermusters:

In der Softwareentwicklung ist das Adaptermuster ein Software-Designmuster, das es ermöglicht, die Schnittstelle einer vorhandenen Klasse von einer anderen Schnittstelle aus zu verwenden. Es wird häufig verwendet, um vorhandene Klassen mit anderen Klassen zusammenarbeiten zu lassen, ohne deren Quellcode zu ändern.

Beispiele aus dem Leben

Das häufigste Ding im Leben ist der Netzsteckeradapter. Die Steckdosenstandards verschiedener Länder auf der ganzen Welt sind unterschiedlich. Wenn Sie den entsprechenden Netzstecker kaufen müssen Dann wäre es eine zu große Geldverschwendung, die Steckdose mitzubringen, die Wände anderer Leute einzureißen und sie neu zu verkabeln.
Es wird also einen Steckeradapter geben, der dazu dient, einen Steckertyp in einen anderen Steckertyp umzuwandeln. Dieses Ding, das als Übertragung zwischen der Steckdose und Ihrer Stromversorgung dient, ist der Adapter.

Anwendung des Adapters in JavaScript (mit Beispielen)

spiegelt sich im Code wider

und wenn ich mich der Programmierung zuwende, ist dies mein persönliches Verständnis:

Konvertieren Sie diese Wenn Sie Verstecken Sie den schmutzigen Code, den Sie nicht sehen möchten, Sie können sagen, dass es sich um einen Adapter handelt

Verbinden Sie sich mit mehreren SDKs von Drittanbietern

Als Beispiel für die tägliche Entwicklung entwickeln wir ein öffentliches WeChat-Konto, WeChat's Nach einer langen Zeit des gemeinsamen Debuggens ist der gesamte Prozess endlich abgeschlossen. Gerade als Sie bereit sind, den Code glücklich zu verpacken und zu starten, erhalten Sie eine neue Anforderung:
Wir Sie müssen darauf zugreifen. Das SDK des offiziellen Alipay-Kontos muss auch über einen Zahlungsprozess verfügen

Um den Code wiederzuverwenden, können wir folgende Logik in das Skript schreiben:

if (platform === 'wechat') {
  wx.pay(config)
} else if (platform === 'alipay') {
  alipay.pay(config)
}

// 做一些后续的逻辑处理
Nach dem Login kopieren

Aber im Allgemeinen sind die von den SDKs der einzelnen Hersteller bereitgestellten Schnittstellenaufrufmethoden etwas unterschiedlich Obwohl manchmal dasselbe Dokument verwendet wird, dank unserer Freunde.

Der obige Code könnte also so aussehen:

// 并不是真实的参数配置,仅仅举例使用
const config = {
  price: 10,
  goodsId: 1
}

// 还有可能返回值的处理方式也不相同
if (platform === 'wechat') {
  config.appId = 'XXX'
  config.secretKey = 'XXX'
  wx.pay(config).then((err, data) => {
    if (err) // error

    // success
  })
} else if (platform === 'alipay') {
  config.token = 'XXX'
  alipay.pay(config, data => {
    // success
  }, err => {
    // error
  })
}
Nach dem Login kopieren

Im Moment ist die Codeschnittstelle ziemlich klar, solange wir die Kommentare gut schreiben .
Aber das Leben ist immer voller Überraschungen und wir haben Anfragen erhalten, das SDK von QQ, das SDK von Meituan, das SDK von Xiaomi oder das SDK einiger Banken hinzuzufügen.

An diesem Punkt könnte Ihr Code so aussehen:

switch (platform) {
  case 'wechat':
    // 微信的处理逻辑
  break
  case 'QQ':
    // QQ的处理逻辑
  break
  case 'alipay':
    // 支付宝的处理逻辑
  break
  case 'meituan':
    // 美团的处理逻辑
  break
  case 'xiaomi':
    // 小米的处理逻辑
  break
}
Nach dem Login kopieren

Dies ist kein Problem mehr, das einige Kommentare ausgleichen können. Ein solcher Code wird immer schwieriger zu pflegen und vielfältiger SDKs sind voller seltsamer Dinge. Wenn andere Leute ähnliche Anforderungen haben und solchen Code neu schreiben müssen, ist dies definitiv eine Verschwendung von Ressourcen.

Um die Klarheit unserer Geschäftslogik zu gewährleisten und zu verhindern, dass zukünftige Generationen wiederholt in diese Falle tappen, werden wir sie aufteilen und als öffentliche Funktion existieren:
Finde eine von ihnen Die Berufung Als Benchmark dient die Methode des SDK oder eine von uns vereinbarte Regel.
Lassen Sie uns dem Anrufer sagen, was Sie tun möchten, wie Sie die Rückgabedaten erhalten können, und dann treffen wir diese verschiedenen schmutzigen Urteile innerhalb der Funktion:

function pay ({
  price,
  goodsId
}) {
  return new Promise((resolve, reject) => {
    const config = {}

    switch (platform) {
      case 'wechat':
        // 微信的处理逻辑
        config.price = price
        config.goodsId = goodsId
        config.appId = 'XXX'
        config.secretKey = 'XXX'
        wx.pay(config).then((err, data) => {
          if (err) return reject(err)

          resolve(data)
        })
      break
      case 'QQ':
        // QQ的处理逻辑
        config.price = price * 100
        config.gid = goodsId
        config.appId = 'XXX'
        config.secretKey = 'XXX'
        config.success = resolve
        config.error = reject
        qq.pay(config)
      break
      case 'alipay':
        // 支付宝的处理逻辑
        config.payment = price
        config.id = goodsId
        config.token = 'XXX'
        alipay.pay(config, resolve, reject)
      break
    }
  })
}
Nach dem Login kopieren

Auf diese Weise, egal in welcher Umgebung wir uns befinden in , sofern unser Adapter dies unterstützt, kann es gemäß den von uns vereinbarten allgemeinen Regeln aufgerufen werden. Das spezifische SDK, das ausgeführt wird, muss sich um den Adapter kümmern:

// run anywhere
await pay({
  price: 10,
  goodsId: 1
})
Nach dem Login kopieren

Für das SDK Anbieter, Sie müssen nur einige Parameter kennen, die Sie benötigen, und dann die Daten auf Ihre eigene Weise zurückgeben.
Für den SDK-Callroom benötigen wir lediglich die gemeinsamen Parameter, auf die wir uns geeinigt haben, und die Überwachung der Callback-Verarbeitung in der vereinbarten Weise.

Die Aufgabe, mehrere SDKs von Drittanbietern zu integrieren, wird dann sehr kompliziert. Dann komprimieren, verschleiern und platzieren wir den Adaptercode in einer unsichtbaren Ecke.

Das ist ungefähr die Rolle von Adaptern. Es muss klar sein, dass es diese umständlichen Codes nicht immer gibt, wenn man sie nicht sieht , verrückt.

Einige andere Beispiele

Ich persönlich denke, dass es in jQuery viele Adapterbeispiele gibt, einschließlich der grundlegendsten $('selector').on. Ist das nicht ein offensichtliches Adaptermuster?

Schrittweises Downgrade und Ausgleich einiger Unterschiede zwischen Browsern, sodass wir einfache on verwenden können, um Ereignisse in Mainstream-Browsern zu überwachen:

// 一个简单的伪代码示例
function on (target, event, callback) {
  if (target.addEventListener) {
    // 标准的监听事件方式
    target.addEventListener(event, callback)
  } else if (target.attachEvent) {
    // IE低版本的监听方式
    target.attachEvent(event, callback)
  } else {
    // 一些低版本的浏览器监听事件方式
    target[`on${event}`] = callback
  }
}
Nach dem Login kopieren

或者在Node中的这样的例子更是常见,因为早年是没有Promise的,所以大多数的异步由callback来完成,且有一个约定好的规则,Error-first callback

const fs = require('fs')

fs.readFile('test.txt', (err, data) => {
  if (err) // 处理异常

  // 处理正确结果
})
Nach dem Login kopieren

而我们的新功能都采用了async/await的方式来进行,当我们需要复用一些老项目中的功能时,直接去修改老项目的代码肯定是不可行的。  
这样的兼容处理需要调用方来做,所以为了让逻辑代码看起来不是太混乱,我们可能会将这样的回调转换为Promise的版本方便我们进行调用:

const fs = require('fs')

function readFile (fileName) {
  return new Promise((resolve, reject) => {
    fs.readFile(fileName, (err, data) => {
      if (err) reject(err)

      resolve(data)
    })
  })
}

await readFile('test.txt')
Nach dem Login kopieren

因为前边也提到了,这种Error-first callback是一个约定好的形式,所以我们可以很轻松的实现一个通用的适配器:

function promisify(func) {
  return (...args) => new Promise((resolve, reject) => {
    func(...args, (err, data) => {
      if (err) reject(err)

      resolve(data)
    })
  })
}
Nach dem Login kopieren

然后在使用前进行对应的转换就可以用我们预期的方式来执行代码:

const fs = require('fs')

const readFile = promisify(fs.readFile)

await readFile('test.txt')
Nach dem Login kopieren
在Node8中,官方已经实现了类似这样的工具函数:util.promisify

小结

个人观点:所有的设计模式都不是凭空想象出来的,肯定是在开发的过程中,总结提炼出的一些高效的方法,这也就意味着,可能你并不需要在刚开始的时候就去生啃这些各种命名高大上的设计模式。  
因为书中所说的场景可能并不全面,也可能针对某些语言,会存在更好的解决办法,所以生搬硬套可能并不会写出有灵魂的代码 :)

Das obige ist der detaillierte Inhalt vonAnwendung des Adapters in JavaScript (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage