国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ES7-Decorator-裝飾者模式

zhangxiangliang / 2596人閱讀

摘要:裝飾者要實(shí)現(xiàn)這些相同的方法繼承自裝飾器對(duì)象創(chuàng)建具體的裝飾器,也是接收作對(duì)參數(shù)接下來我們要為每一個(gè)功能創(chuàng)建一個(gè)裝飾者對(duì)象,重寫父級(jí)方法,添加我們想要的功能。

裝飾模式
僅僅包裝現(xiàn)有的模塊,使之 “更加華麗” ,并不會(huì)影響原有接口的功能 —— 好比你給手機(jī)添加一個(gè)外殼罷了,并不影響手機(jī)原有的通話、充電等功能;
使用 ES7 的 decorator

ES7 中增加了一個(gè) decorator 屬性,它借鑒自 Python

下面我們以 鋼鐵俠 為例講解如何使用 ES7decorator

以鋼鐵俠為例,鋼鐵俠本質(zhì)是一個(gè)人,只是“裝飾”了很多武器方才變得那么 NB,不過再怎么裝飾他還是一個(gè)人。

我們的示例場景是這樣的

首先創(chuàng)建一個(gè)普通的Man類,它的抵御值 2,攻擊力為 3,血量為 3;

然后我們讓其帶上鋼鐵俠的盔甲,這樣他的抵御力增加 100,變成 102;

讓其帶上光束手套,攻擊力增加 50,變成 53;

最后讓他增加“飛行”能力

【Demo 1】對(duì)方法的裝飾:裝備盔甲

創(chuàng)建 Man 類:

class Man{
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  init(def,atk,hp){
    this.def = def; // 防御值
    this.atk = atk;  // 攻擊力
    this.hp = hp;  // 血量
  }
  toString(){
    return `防御力:${this.def},攻擊力:${this.atk},血量:${this.hp}`;
  }
}

var tony = new Man();

console.log(`當(dāng)前狀態(tài) ===> ${tony}`);

// 輸出:當(dāng)前狀態(tài) ===> 防御力:2,攻擊力:3,血量:3
代碼直接放在 http://babeljs.io/repl/ 中運(yùn)行查看結(jié)果,
記得勾選SettingEvaluate選項(xiàng),和 options的選項(xiàng)為legacy

創(chuàng)建 decorateArmour 方法,為鋼鐵俠裝配盔甲——注意 decorateArmour 是裝飾在方法init上的。

function decorateArmour(target, key, descriptor) {
  const method = descriptor.value;
  let moreDef = 100;
  let ret;
  descriptor.value = (...args)=>{
    args[0] += moreDef;
    ret = method.apply(target, args);
    return ret;
  }
  return descriptor;
}

class Man{
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  init(def,atk,hp){
    this.def = def; // 防御值
    this.atk = atk;  // 攻擊力
    this.hp = hp;  // 血量
  }
  toString(){
    return `防御力:${this.def},攻擊力:${this.atk},血量:${this.hp}`;
  }
}

var tony = new Man();

console.log(`當(dāng)前狀態(tài) ===> ${tony}`);
// 輸出:當(dāng)前狀態(tài) ===> 防御力:102,攻擊力:3,血量:3

我們先看輸出結(jié)果,防御力的確增加了 100,看來盔甲起作用了。

Decorators 的本質(zhì)是利用了 ES5Object.defineProperty 屬性,這三個(gè)參數(shù)其實(shí)是和 Object.defineProperty 參數(shù)一致的

【Demo 2】裝飾器疊加:增加光束手套

在上面的示例中,我們成功為 普通人 增加 “盔甲” 這個(gè)裝飾;現(xiàn)在我想再給他增加 “光束手套”,希望額外增加 50 點(diǎn)防御值。

...
function decorateLight(target, key, descriptor) {
  const method = descriptor.value;
  let moreAtk = 50;
  let ret;
  descriptor.value = (...args)=>{
    args[1] += moreAtk;
    ret = method.apply(target, args);
    return ret;
  }
  return descriptor;
}

class Man{
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  @decorateLight
  init(def,atk,hp){
    this.def = def; // 防御值
    this.atk = atk;  // 攻擊力
    this.hp = hp;  // 血量
  }
...
}
var tony = new Man();
console.log(`當(dāng)前狀態(tài) ===> ${tony}`);
//輸出:當(dāng)前狀態(tài) ===> 防御力:102,攻擊力:53,血量:3

在這里你就能看出裝飾模式的優(yōu)勢(shì)了,它可以對(duì)某個(gè)方法進(jìn)行疊加使用,對(duì)原類的侵入性非常小,只是增加一行@decorateLight而已,可以方便地增刪;(同時(shí)還可以復(fù)用)

【Demo 3】對(duì)類的裝飾:增加飛行能力

裝飾模式有兩種:純粹的裝飾模式 和 半透明的裝飾模式。

上述的兩個(gè) demo 中所使用的應(yīng)該是 純粹的裝飾模式,它并不增加對(duì)原有類的接口;下面要講 demo 是給普通人增加“飛行”能力,相當(dāng)于給類新增一個(gè)方法,屬于 半透明的裝飾模式,有點(diǎn)兒像適配器模式的樣子。

...

// 3
function addFly(canFly){
  return function(target){
    target.canFly = canFly;
    let extra = canFly ? "(技能加成:飛行能力)" : "";
    let method = target.prototype.toString;
    target.prototype.toString = (...args)=>{
      return method.apply(target.prototype,args) + extra;
    }
    return target;
  }
}

@addFly(true)
class Man{
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  @decorateLight
  init(def,atk,hp){
    this.def = def; // 防御值
    this.atk = atk;  // 攻擊力
    this.hp = hp;  // 血量
  }
  ...
}
...

console.log(`當(dāng)前狀態(tài) ===> ${tony}`);
// 輸出:當(dāng)前狀態(tài) ===> 防御力:102,攻擊力:53,血量:3(技能加成:飛行能力)

作用在方法上的 decorator 接收的第一個(gè)參數(shù)(target )是類的 prototype;如果把一個(gè) decorator 作用到類上,則它的第一個(gè)參數(shù) target 是 類本身。

使用原生 JS 實(shí)現(xiàn)裝飾器模式

Man 是具體的類,Decorator 是針對(duì) Man 的裝飾器基類

具體的裝飾類 DecorateArmour 典型地使用 prototype 繼承方式 繼承自 Decorator 基類;

基于 IOC(控制反轉(zhuǎn))思想 ,Decorator 是接受 Man 類,而不是自己創(chuàng)建 Man 類;

// 首先我們要?jiǎng)?chuàng)建一個(gè)基類
function Man(){

  this.def = 2;
  this.atk = 3;
  this.hp = 3;
}

// 裝飾者也需要實(shí)現(xiàn)這些方法,遵守 Man 的接口
Man.prototype={
  toString:function(){
    return `防御力:${this.def},攻擊力:${this.atk},血量:${this.hp}`;
  }
}
// 創(chuàng)建裝飾器,接收 Man 對(duì)象作為參數(shù)。
var Decorator = function(man){
  this.man = man;
}

// 裝飾者要實(shí)現(xiàn)這些相同的方法
Decorator.prototype.toString = function(){
    return this.man.toString();
}

// 繼承自裝飾器對(duì)象
// 創(chuàng)建具體的裝飾器,也是接收 Man 作對(duì)參數(shù)
var DecorateArmour = function(man){

  var moreDef = 100;
  man.def += moreDef;
  Decorator.call(this,man);

}
DecorateArmour.prototype = new Decorator();

// 接下來我們要為每一個(gè)功能創(chuàng)建一個(gè)裝飾者對(duì)象,重寫父級(jí)方法,添加我們想要的功能。
DecorateArmour.prototype.toString = function(){
  return this.man.toString();
}

// 注意這里的調(diào)用方式
// 構(gòu)造器相當(dāng)于“過濾器”,面向切面的
var tony = new Man();
tony = new DecorateArmour(tony);
console.log(`當(dāng)前狀態(tài) ===> ${tony}`);
// 輸出:當(dāng)前狀態(tài) ===> 防御力:102,攻擊力:3,血量:3
經(jīng)典實(shí)現(xiàn):Logger

經(jīng)典應(yīng)用就是 日志系統(tǒng) 了,那么我們也用 ES7 的語法給鋼鐵俠打造一個(gè)日志系統(tǒng)吧。

/**
 * Created by jscon on 15/10/16.
 */
let log = (type) => {

  return (target, name, descriptor) => {
    const method = descriptor.value;
    descriptor.value =  (...args) => {
      console.info(`(${type}) 正在執(zhí)行: ${name}(${args}) = ?`);
      let ret;
      try {
        ret = method.apply(target, args);
        console.info(`(${type}) 成功 : ${name}(${args}) => ${ret}`);
      } catch (error) {
        console.error(`(${type}) 失敗: ${name}(${args}) => ${error}`);
      }
      return ret;
    }
  }
}
class IronMan {
  @log("IronMan 自檢階段")
  check(){
    return "檢查完畢";
  }
  @log("IronMan 攻擊階段")
  attack(){
    return "擊倒敵人";
  }
  @log("IronMan 機(jī)體報(bào)錯(cuò)")
  error(){
    throw "Something is wrong!";
  }
}

var tony = new IronMan();
tony.check();
tony.attack();
tony.error();

// 輸出:
// (IronMan 自檢階段) 正在執(zhí)行: check() = ?
// (IronMan 自檢階段) 成功 : check() => 檢查完畢
// (IronMan 攻擊階段) 正在執(zhí)行: attack() = ?
// (IronMan 攻擊階段) 成功 : attack() => 擊倒敵人
// (IronMan 機(jī)體報(bào)錯(cuò)) 正在執(zhí)行: error() = ?
// (IronMan 機(jī)體報(bào)錯(cuò)) 失敗: error() => Something is wrong!

Logger 方法的關(guān)鍵在于:

首先使用 const method = descriptor.value; 將原有方法提取出來,保障原有方法的純凈;

try..catch 語句是 調(diào)用 ret = method.apply(target, args);在調(diào)用之前之后分別進(jìn)行日志匯報(bào);

最后返回 return ret; 原始的調(diào)用結(jié)果

相關(guān)庫

https://github.com/jayphelps/...

vue中使用裝飾器實(shí)現(xiàn)AOP編程

JavaScript中實(shí)現(xiàn)AOP,是把一個(gè)函數(shù)“動(dòng)態(tài)織入”到另一個(gè)函數(shù)之中。
首先要構(gòu)造Functionprototype

//prototype.js
Function.prototype.before = function (beforefn) {
  let _self = this;
  return function () {
    beforefn.apply(this, arguments);
    return _self.apply(this, arguments);
  };
};
Function.prototype.after = function (afterfn) {
  let _self = this;
  return function () {
    let ret = _self.apply(this, arguments);
    afterfn.apply(this, arguments);
    return ret;
  };
};
Function.prototype.around = function (beforefn, afterfn) {
  let _self = this;
  return function () {
    beforefn.apply(this, arguments);
    let ret = _self.apply(this, arguments);
    afterfn.apply(this, arguments);
    return ret;
  };
};

編輯我們的裝飾器函數(shù)

//decorator.js
export const before = function (...args) {
  return function (target, key, descriptor) {
    descriptor.value = descriptor.value.before(() => {
      console.log(`Action-${key} 觸發(fā)埋點(diǎn)!`);
    });
  };
};
export const after = function (...args) {
  return function (target, key, descriptor) {
    descriptor.value = descriptor.value.after(() => {
      console.log(`Action-${key} 觸發(fā)埋點(diǎn)!`);
    });
  };
};
export const around = function (...args) {
  return function (target, key, descriptor) {
    descriptor.value = descriptor.value.around(() => {
      console.log(`Action-${key} 觸發(fā)埋點(diǎn)before!`);
    }, () => {
      console.log(`Action-${key} 觸發(fā)埋點(diǎn)after!`);
    });
  };
};

編輯我們的vue文件

//test.vue

.babelrc文件

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}
摘自

http://www.liuweibo.cn/p/254#...

淘寶前端團(tuán)隊(duì)

https://www.jianshu.com/p/208...

今日?qǐng)D 羞羞噠

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/109784.html

相關(guān)文章

  • Java 設(shè)計(jì)模式裝飾模式

    摘要:裝飾者模式組成結(jié)構(gòu)抽象構(gòu)件給出抽象接口或抽象類,以規(guī)范準(zhǔn)備接收附加功能的對(duì)象。裝飾者模式圖解裝飾者模式應(yīng)用場景需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類添加附加職責(zé)。裝飾者對(duì)象接受所有來自客戶端的請(qǐng)求。參考資料設(shè)計(jì)模式 一、了解裝飾者模式 1.1 什么是裝飾者模式 裝飾者模式指的是在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾者來包裹真實(shí)的對(duì)...

    kumfo 評(píng)論0 收藏0
  • 設(shè)計(jì)模式裝飾模式

    摘要:相關(guān)設(shè)計(jì)模式裝飾者模式和代理模式裝飾者模式關(guān)注再一個(gè)對(duì)象上動(dòng)態(tài)添加方法代理模式關(guān)注再對(duì)代理對(duì)象的控制訪問,可以對(duì)客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關(guān)于新職責(zé)適配器也可以在轉(zhuǎn)換時(shí)增加新的職責(zé),但主要目的不在此。 0x01.定義與類型 定義:裝飾模式指的是在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來包裹真實(shí)的...

    chuyao 評(píng)論0 收藏0
  • 設(shè)計(jì)模式——裝飾模式

    摘要:裝飾者模式遵循了開閉原則,對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。但是在使用裝飾者模式的同時(shí)可能會(huì)引入大量小類,而且使用裝飾者模式除了實(shí)例化組件外,還要把組件包裝進(jìn)裝飾者,會(huì)使代碼顯得不易理解。 1. 簡介 ??裝飾者模式是一種結(jié)構(gòu)型模式,它可以動(dòng)態(tài)的將責(zé)任附加到對(duì)象上,在擴(kuò)展功能方面,它比繼承更有彈性。裝飾者模式遵循了開閉原則,對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。??雖然在裝飾者模式中也使用了繼承,但是繼承只是...

    hoohack 評(píng)論0 收藏0
  • 代理模式裝飾模式

    摘要:簡介代理模式和裝飾者模式是兩種常見的設(shè)計(jì)模式。這里通過構(gòu)造函數(shù)的參數(shù)將被代理對(duì)象傳入到代理中,也可以通過其它方式,如提供一個(gè)方法。下面是的代碼輸出首先依然是先創(chuàng)建一個(gè)需要被代理的對(duì)象,然后把它傳入到的構(gòu)造函數(shù)中。 簡介 代理模式和裝飾者模式是兩種常見的設(shè)計(jì)模式。代理模式是為其它對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以...

    NusterCache 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<