通过例子持续学习JS设计模式中,接下来请跟随我的步伐走进我的学习笔记世界~
什么是设计模式?我们为什么需要学习设计模式?
设计模式是可以更好解决问题的一种方案。
这意味着什么?如果你开发的项目的功能是固定的,永远不会调整业务,那么你就不需要使用设计模式等任何技巧。您只需要使用通常的方式编写代码并完成需求即可。
但是,我们的开发项目的需求是不断变化的,这就需要我们经常修改我们的代码。也就是说,我们现在写代码的时候,需要为未来业务需求可能发生的变化做好准备。
这时,你会发现使用设计模式可以让你的代码更具可扩展性。
1 命令模式
-  我的理解: 
 定义一个类,里面写方法,用的时候引入这个类,调用类.方法()使用。
-  定义: 
 有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
  
-  适用场景:绘制按钮,不知道某个按钮未来将用来做什么,可能用来刷新菜单界面,也可能用来增加一些子菜单,只知道点击这个按钮会发生某些事情。那么当完成这个按钮的绘制之后,应该如何给它绑定onclick 事件呢? 我们很快可以找到在这里运用命令模式的理由:点击了按钮之后,必须向某些负责具体行为的对象发送请求,这些对象就是请求的接收者。但是目前并不知道接收者是什么对象,也不知道接收者究竟会做什么。此时我们需要借助命令对象的帮助,以便解开按钮和负责具体行为对象之间的耦合。 
const btn1 = function () {};
const btn2 = function () {};
// 定义一个命令发布者的类
class Executor {
    setCommand(btn, command) {
        btn.onclick = function() {
            command.execute()
        }
    }
}
// 定义一个命令接收者
class Menu {
    refresh() {
        console.log('刷新菜单')
    }
    addSubMenu() {
        console.log('增加子菜单')
    }
}
// 定义一个刷新菜单的命令对象的类
class RefreshMenu {
    constructor(receiver) {
        // 命令对象与接收者关联
        this.receiver = receiver
    }
    // 暴露出统一的接口给命令发布者Executor
    execute() {
        this.receiver.refresh()
    }
}
// 定义一个增加子菜单的命令对象的类
class AddSubMenu {
    constructor(receiver) {
        // 命令对象与接收者关联
        this.receiver = receiver
    }
    // 暴露出统一的接口给命令发布者Executor
    execute() {
        this.receiver.addSubMenu()
    }
}
var menu = new Menu()
var executor = new Executor()
var refreshMenu = new RefreshMenu(menu)
// 给按钮1添加刷新功能
executor.setCommand(btn1, refreshMenu)
var addSubMenu = new AddSubMenu(menu)
// 给按钮2添加增加子菜单功能
executor.setCommand(btn2, addSubMenu)
// 如果想给按钮3增加删除菜单的功能,就继续增加删除菜单的命令对象和接收者的具体删除方法,而不必修改命令对象
btn1.onclick();
btn2.onclick();
2 单例模式
- 定义
 保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
- 适用场景:
 一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。
class CreateUser {
    constructor(name) {
        this.name = name;
        this.getName();
    }
    getName() {
         return this.name;
    }
}
// 代理实现单例模式
var ProxyMode = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {
            instance = new CreateUser(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例
var a = new ProxyMode("aaa");
var b = new ProxyMode("bbb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的
console.log(a === b);    //true
3 策略模式
- 定义:
 定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
 策略模式的目的就是将算法的使用和算法的实现分离开来。
- 适用场景
 如果您的函数具有以下特征:判断条件很多;各个判断条件下的代码相互独立。然后,你可以将每个判断条件下的代码封装成一个独立的函数,接着,建立判断条件和具体策略的映射关系,使用策略模式重构你的代码。
/** 假设您目前正在从事一个电子商务商店的项目。
* 每个产品都有一个原价,我们可以称之为 originalPrice。
* 但并非所有产品都以原价出售,我们可能会推出允许以折扣价
* 出售商品的促销活动。商家可以在后台为产品设置不同的状态。
* 然后实际售价将根据产品状态和原价动态调整。 
* 具体规则:xxxxxxxxx;
* 如果你需要写一个getPrice函数,你应该怎么写呢?*/
let priceStrategies = {
  'pre-sale': preSalePrice,
  'promotion': promotionPrice,
  'black-friday': blackFridayPrice,
  'default': defaultPrice
}
function getPrice(originalPrice, status) {
  return priceStrategies[status](originalPrice)
}
function blackFridayPrice(origialPrice) {
  if (origialPrice >= 100 && originalPrice < 200) {
    return origialPrice - 20
  } else if (originalPrice >= 200) {
    return originalPrice - 50
  } else {
    return originalPrice * 0.8
  }
}
function defaultPrice(origialPrice) {
  return origialPrice
}
function getPrice(originalPrice, status) {
  if (status === 'pre-sale') {
    return preSalePrice(originalPrice)
  }
  if (status === 'promotion') {
    return promotionPrice(originalPrice)
  }
  if (status === 'black-friday') {
    return blackFridayPrice(originalPrice)
  }
  if(status === 'default'){
    return defaultPrice(originalPrice)
  }
}















![[网络安全]在win2000虚拟机上创建隐藏账户](https://img-blog.csdnimg.cn/direct/17e375bd0c094c97920361bd82f2ec7d.bmp)



