javascript设计模式2

结构型模式

  1. 享元模式:运用共享技术来减少创建对象的数量,从而减少内存占用提高性能
    模式下将对象属性分为内部和外部
  • 内部:可以被对象集合共享,通常不会改变
  • 外部:根据应用场景而改变
    利用时间来换取空间的优化模式,应用于需要大量创建重复类的代码块
//对象池
class ObjectPool{
  constructor(){ this._pool=[]; }
  //创建对象
  create(obj){
    return this._pool.length===0 ?
    new obj(this) : this._pool.shift();
  }
  //对象回收
  recover(obj){
    return this._pool.push(obj)
  }
  //大小
  size(){
  return this._pool.length;
  }
}

// 模拟文件对象
class File {
  constructor(pool) {
    this.pool = pool;
  }

  // 模拟下载操作
  download() {
    console.log(`+ 从 ${this.src} 开始下载 ${this.name}`);
    setTimeout(() => {
      console.log(`- ${this.name} 下载完毕`); // 下载完毕后, 将对象重新放入对象池
      this.pool.recover(this);
    }, 100);
  }
}

let objPool = new ObjectPool();

let file1 = objPool.create(File);
file1.name = "文件1";
file1.src = "https://download1.com";
file1.download();

let file2 = objPool.create(File);
file2.name = "文件2";
file2.src = "https://download2.com";
file2.download();

setTimeout(() => {
  let file3 = objPool.create(File);
  file3.name = "文件3";
  file3.src = "https://download3.com";
  file3.download();
}, 200);

setTimeout(
  () =>
    console.log(
      `${"*".repeat(50)}\n下载了3个文件,但其实只创建了${objPool.size()}个对象`
    ),
  1000
);
  1. 代理模式:解决避免对一些对象的直接访问
// main.js
const myImg = {
  setSrc(imgNode, src) {
    imgNode.src = src;
  }
};

// 利用代理模式实现图片懒加载
const proxyImg = {
  setSrc(imgNode, src) {
    myImg.setSrc(imgNode, "./image.png"); // NO1. 加载占位图片并且将图片放入元素

    let img = new Image();
    img.onload = () => {
      myImg.setSrc(imgNode, src); // NO3. 完成加载后, 更新  元素中的图片
    };
    img.src = src; // NO2. 加载真正需要的图片
  }
};

let imgNode = document.createElement("img"),
  imgSrc =
    "https://upload-images.jianshu.io/upload_images/5486602-5cab95ba00b272bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp";

document.body.appendChild(imgNode);

proxyImg.setSrc(imgNode, imgSrc);
  1. 桥接模式:抽象部分和具体实现部分分离,两者可独立变化,也可以一起工作
//此函数负责循环遍历数组每个元素,是抽象部分; 而回调函数callback就是具体实现部分。
const foreach=(arr,callback){
if(!Array.isArray(arr)){
  return;
}
const length=arr.length;
for(let i=0;i console.log(el,index)))
  1. 组合模式(树形模式)将对象组合成树形结构以表示“部分-整体”的层次结构。
// 文件类
class File {
  constructor(name) {
    this.name = name || "File";
  }

  add() {
    throw new Error("文件夹下面不能添加文件");
  }

  scan() {
    console.log("扫描文件: " + this.name);
  }
}

// 文件夹类
class Folder {
  constructor(name) {
    this.name = name || "Folder";
    this.files = [];
  }

  add(file) {
    this.files.push(file);
  }

  scan() {
    console.log("扫描文件夹: " + this.name);
    for (let file of this.files) {
      file.scan();
    }
  }
}

let home = new Folder("用户根目录");

let folder1 = new Folder("第一个文件夹"),
  folder2 = new Folder("第二个文件夹");

let file1 = new File("1号文件"),
  file2 = new File("2号文件"),
  file3 = new File("3号文件");

// 将文件添加到对应文件夹中
folder1.add(file1);

folder2.add(file2);
folder2.add(file3);

// 将文件夹添加到更高级的目录文件夹中
home.add(folder1);
home.add(folder2);

// 扫描目录文件夹
home.scan();
  1. 装饰者模式:在不改变自身属性的基础上,动态添加功能代码
const addDecorator = (fn, before, after) => {
  let isFn = fn => typeof fn === "function";

  if (!isFn(fn)) {
    return () => {};
  }

  return (...args) => {
    let result;
    // 按照顺序执行“装饰函数”
    isFn(before) && before(...args);
    // 保存返回函数结果
    isFn(fn) && (result = fn(...args));
    isFn(after) && after(...args);
    // 最后返回结果
    return result;
  };
};

/******************以下是测试代码******************/

const beforeHello = (...args) => {
  console.log(`Before Hello, args are ${args}`);
};

const hello = (name = "user") => {
  console.log(`Hello, ${name}`);
  return name;
};

const afterHello = (...args) => {
  console.log(`After Hello, args are ${args}`);
};

const wrappedHello = addDecorator(hello, beforeHello, afterHello);

let result = wrappedHello("test.com");
console.log(result);

6.适配器模式:为多个不兼容接口之间提供“转化器”。
当数据不符合使用规则,就可以借助此种模式进行格式转化。

const API = {
  qq: () => ({
    n: "菊花台",
    a: "周杰伦",
    f: 1
  }),
  netease: () => ({
    name: "菊花台",
    author: "周杰伦",
    f: false
  })
};

const adapter = (info = {}) => ({
  name: info.name || info.n,
  author: info.author || info.a,
  free: !!info.f
});

/*************测试函数***************/

console.log(adapter(API.qq()));
console.log(adapter(API.netease()));

你可能感兴趣的:(javascript设计模式2)