LzayMan 的实现

in 技术 with 0 comment

LazyMan 题目介绍

实现一个 LazyMan,可以按照以下方式调用:

LazyMan("Hank")输出:

Hi! This is Hank!


LazyMan("Hank").sleep(10).eat("dinner")输出

Hi! This is Hank!

//等待 10 秒..

Wake up after 10

Eat dinner~


LazyMan("Hank").eat("dinner").eat("supper")输出

Hi This is Hank!

Eat dinner~

Eat supper~


LazyMan("Hank").sleepFirst(5).eat("supper")输出

//等待 5 秒

Wake up after 5

Hi This is Hank!

Eat supper


以此类推。

考点

es6 实现

/**
 * lazyman匿名类
 * @class _LazyMan
 */
class _LazyMan {
  // 任务列表
  taskList = [];
  // 发布实际上调用的方法
  runFunc = {
    hi(thisClass, name) {
      thisClass.log(`Hi, this is ${name}!`);
      thisClass.publish();
    },
    eat(thisClass, food) {
      thisClass.log(`Eat ${food}~`);
      thisClass.publish();
    },
    sleep(thisClass, time) {
      setTimeout(() => {
        thisClass.log(`Wake up after ${time}!`);
        thisClass.publish();
      }, time * 1000);
    },
    sleepFirst(thisClass, time) {
      thisClass.runFunc.sleep(thisClass, time);
    }
  };
  constructor(name) {
    this.hi(name);

    // 触发发布
    setTimeout(() => {
      this.publish();
    });
  }

  hi(name) {
    this.subscribe('hi', name);
    return this;
  }

  // 暴露给外部的方法
  eat(food) {
    this.subscribe('eat', food);

    // 实现链式调用的关键
    return this;
  }

  sleep(time) {
    this.subscribe('sleep', time);
    return this;
  }

  sleepFirst(time) {
    this.subscribe('sleepFirst', time);
    return this;
  }

  // 订阅
  subscribe(funcName, ...args) {
    const task = {
      name: funcName,
      args
    };
    if (funcName === 'sleepFirst') {
      this.taskList.unshift(task);
    } else {
      this.taskList.push(task);
    }
  }

  // 发布
  publish() {
    if (this.taskList.length > 0) {
      this.run(this.taskList.shift());
    }
  }

  // 执行
  run(task) {
    this.runFunc[task.name](this, ...task.args);
  }

  // 打印
  log(str) {
    console.log(str);
  }
}

// 暴露给外部的方法
function LazyMan(name) {
  return new _LazyMan(name);
}

// 调用
LazyMan('Tom')
  .eat('lunch')
  .sleep(2)
  .eat('dinner')
  .sleepFirst(1);

// 结果:
// Wake up after 1!
// Hi, this is Tom!
// Eat lunch~
// Wake up after 2!
// Eat dinner~

typescript 实现

// 定义任务模型
interface Task {
  name: string;
  args: any[];
}

/**
 * lazyman匿名类
 * @class _LazyMan
 */
class _LazyMan {
  // 任务列表
  private taskList: Task[] = [];
  // 发布实际上调用的方法
  private runFunc = {
    hi(thisClass: _LazyMan, name: string) {
      thisClass.log(`Hi, this is ${name}!`);
      thisClass.publish();
    },
    eat(thisClass: _LazyMan, food: string) {
      thisClass.log(`Eat ${food}~`);
      thisClass.publish();
    },
    sleep(thisClass: _LazyMan, time: number) {
      setTimeout(() => {
        thisClass.log(`Wake up after ${time}!`);
        thisClass.publish();
      }, time * 1000);
    },
    sleepFirst(thisClass: _LazyMan, time: number) {
      thisClass.runFunc.sleep(thisClass, time);
    }
  };
  constructor(name: string) {
    this.hi(name);

    // 触发发布
    setTimeout(() => {
      this.publish();
    });
  }

  private hi(name: string) {
    this.subscribe('hi', name);
    return this;
  }

  // 暴露给外部的方法
  eat(food: string) {
    this.subscribe('eat', food);

    // 实现链式调用的关键
    return this;
  }

  sleep(time: number) {
    this.subscribe('sleep', time);
    return this;
  }

  sleepFirst(time: number) {
    this.subscribe('sleepFirst', time);
    return this;
  }

  // 订阅
  private subscribe(funcName: string, ...args: any[]) {
    const task: Task = {
      name: funcName,
      args
    };
    if (funcName === 'sleepFirst') {
      this.taskList.unshift(task);
    } else {
      this.taskList.push(task);
    }
  }

  // 发布
  private publish() {
    if (this.taskList.length > 0) {
      this.run(this.taskList.shift());
    }
  }

  // 执行
  private run(task: Task) {
    this.runFunc[task.name](this, ...task.args);
  }

  // 打印
  private log(str: string) {
    console.log(str);
  }
}

// 暴露给外部的方法
function LazyMan(name: string) {
  return new _LazyMan(name);
}

// 调用
LazyMan('Tom')
  .eat('lunch')
  .sleep(2)
  .eat('dinner')
  .sleepFirst(1);

参考

Responses