javascript设计模式(代码片段)

SpicyPeper SpicyPeper     2023-04-26     144

关键词:

JavaScript设计模式

设计模式概念

经过代码设计经验总结之后设计出的一种固定解决问题的方式

设计模式作用

  • 代码复用

  • 保证代码可靠性

  • 将编程工程化

  • 更易被他人理解

设计模式的分类(W3C平台)

构造器模式,模块化模式,暴露模块模式,单例模式,中介者模式,原型模式,命令模式,外观模式,工厂模式,Mixin模式,装饰模式,亨元(Flyweight)模式,MVC模式,MVP模式,MVVM模式,组合模式,适配器模式,外观模式,观察者模式,迭代器模式,惰性初始模式,代理模式,建造者模式,...

常用设计模式

1. 单例模式

概念 :

多次操作是在同一个实例对象上实现 即第一次为创建实例对象 后面的都是在原有的实例对象上操作

优点 :

节省性能 提升执行速度

  function Fn()
      // 这里自定义__obj__是为了防止和Fn内置对象名重叠
      if(!Fn.__obj__)
          // 这里没有这个对象存在再创建 有则不创建
          // 保证单例的核心
          Fn.__obj__ = ;
      
      Fn.__obj__.name = "admin";
      return Fn.__obj__;
  

2. 工厂模式

概念 :

多次创建多个具有相同属性名相同方法功能的不同实例对象

工厂模式的标志 :

原料(创建基础对象) 加工(给基础对象添加属性或方法) 出厂(将基础对象返回到外部)

优点 :

相互独立 分别控制 互不干扰

  function Fn(name, age)
    this.name = name;
    this.age = age
  
  const f1 = new Fn("admin", 18)
  const f2 = new Fn("root", 19)
  // 工厂模式和单例模式不同 每次创建的都是新实例对象
  console.log(f1 === f2);
  // false

3. 抽象工厂模式

概念 :

在工厂模式的基础上进行二次封装,将相同的属性值再次封装

  // 造车厂
  function CreateCar(brand, color, type)
    this.brand = brand;
    this.color = color;
    this.type = type;
  

  // 专门用来生产比亚迪的生产线
  function BYDCar(color, type)
    return new CreateCar("比亚迪", color, type);
  

  const b1 = new BYDCar("白色", "SUV");
  const b2 = new BYDCar("红色", "轿车");

  // 专门用来生产大众的生产线
  function WCar(color, type)
    return new CreateCar("大众", color, type);
  

  const w1 = new WCar("黑色", "SUV");
  const w2 = new WCar("灰色", "轿车");

4. 适配器模式

概念 :

解决两个软件实体间的接口不兼容的问题,对不兼容的部分进行适配

例 : 手机没有3.5耳机插口,所以就需要增加一个转接头来完成适配功能以确保耳机的正常使用

  // 创建一个手机构造器 有打电话打游戏功能
  function CreatePhone()
    this.name = "手机"
    this.call = function()
      console.log("打电话")
    
    this.game = function()
      console.log("玩游戏")
    
  

  // 创建一个电脑构造器 有游戏功能
  function CreateComputer()
    this.name = "电脑"
    this.game = function()
      console.log("玩游戏")
    
  

  // 测试打电话和游戏功能
  function test(obj)
    obj.call();
    obj.game();
  

  const p = new CreatePhone()
  const c = new CreateComputer()

  // 如果没有适配器 电脑因为没有打电话功能test会报错
  function Adapter(obj)
    // 如果没有这个功能则定义一个这个功能
    if(!obj.call)
      obj.call = function()
        console.log("这是" + obj.name + "没有打电话功能")
      
    
    return obj;
  

  test(p);
  // 打电话
  // 玩游戏
  test( Adapter(c) );
  // 这是电脑没有打电话功能
  // 玩游戏

  console.log(p)
  console.log(c)

5. 代理模式

概念

不直接访问对象 而是提供一个中间对象(代理)来控制对这个对象的访问

生活中也有比较常见的代理模式:中介、寄卖、经纪人等等

  // 发送数据方 target为接收方 name为发送方名字
  function sender(target, name)
    this.name = name;
    // 定义发送方式
    this.send = function(msg)
      console.log(this.name + "将" + msg + "交给了" + target.name);
    
  

  // 接收数据方 name为接收方名字
  function reciver(name)
    this.name = name;
  

  // 创建\'bob\'实例对象用于接收数据
  const s = new reciver("bob");

  // 定义中间代理 target为接收方
  function poster(target)
    // 创建发送方实例对象
    const f = new sender(s, "tom");
    //message用于存储各种数据
    this.message = [];
    this.send = function(msg)
      this.message.push(
        发件人: f.name,
        收件人: target.name,
        物品: msg,
        时间: Date.now()
      )
      //调用发送方send方法 msg为传进来参数
      f.send(msg);
    
  

  // 创建代理实例对象
  const k = new poster(s);
  // 代理发送方tom发送数据给接收方bob
  k.send("一批教材");
  k.send("一批教具");
  k.send("一批学生");

  console.log(k.message);

6. 观察者模式

又称发布订阅模式(Publish/Subscribe)

概念

观察者模式定义了一种一对多的关系 让一个对象(发布者Dep)能被多个观察者(订阅者Observer)同时监听

优点

  • 支持简单的广播通信 自动通知所有订阅者
  • 页面载入后发布者很容易与观察者存在一种动态关联 增加了灵活性
  • 发布者与观察者之间的抽象耦合关系能够单独扩展以及重用(解耦)
  function MyEvent() 
    // 定义一个对象存储dep和数组形式的observer
    this.message = ;

    // 绑定发布者和目标订阅者
    this.binding = function(dep, observer) 
      if (this.message[dep]) 
        // 发布者存在 则加入新的订阅者
        this.message[dep].push(observer);
       else 
        // 发布者不存在 则创建一个数组 存入第一个订阅者
        this.message[dep] = [observer];
      
    

    // 绑定发布者和目标订阅者
    this.unbinding = function(dep, observer) 
      // 发布者不存在 则返回
      if (!this.message[dep]) return;
      // 找到订阅者在数组中的索引
      var index = this.message[dep].indexOf(observer);
      if (index != -1) 
        // 如果有 则从索引位置删除他
        this.message[dep].splice(index, 1);
      
    
    
    // 执行目标发布者的所有订阅者的行为
    this.emit = function(dep) 
      // 发布者不存在 则返回
      if (!this.message[dep]) return;
      // 调用所有订阅者方法
      this.message[dep].forEach((val) => val(dep);)
    
  

  // 创建实例对象
  const event = new MyEvent();

  // 绑定发布者和订阅者
  event.binding(\'bob\', follower1);
  event.binding(\'bob\', follower2);

  event.binding(\'tom\', follower1);
  event.binding(\'tom\', follower2);

  // 解绑发布者和目标订阅者
  event.unbinding(\'tom\', follower1);

  // 执行目标发布者所有订阅者行为
  event.emit(\'bob\');
  event.emit(\'tom\');

  // 定义订阅者行为
  function follower1(dep) 
    console.log(\'follower1订阅了\' + dep)
  
  function follower2(dep) 
    console.log(\'follower2我订阅了\' + dep)
  

7. 策略模式

概念 :

将多个功能封装起来 定义一系列算法 并使他们能直接相互替换

优点 :

  • 利用组合 委托 避免了条件语句
  • 使代码更易理解和扩展
  • 代码复用
  // 需求: 绩效计算
  // 条件选择方式 if分支随着绩效分类增多而增多 影响性能
  let bonus = function (performance, salary) 
    if(performance == "S") 
      return salary * 4;
     else if (performance == "A") 
      return salary * 3;
     else if (performance == "B")
      return salary * 2;
  

  // 策略模式
  
  let calculateBonus = 
    "S": function ( salary )
      return salary * 4;
    ,
    "A": function ( salary ) 
      return salary * 3;
    ,
    "B": function ( salary )  
      return salary * 2;
    
  

  function calculate(level, salary) 
    return calculateBonus[level](salary);
  

  console.log(calculate(\'S\', 20000) + \'$\')

8. MVC模式

全名: Model View Controller 模型 视图 控制器

  • M: 模型 按照要求来取出数据
  • V: 视图 用户直观看到的页面
  • C: 控制器 向系统发出指令的工具

优点

  • 降低代码耦合
  • 分工合作 提高开发效率
  • 组件重用

工作流程

  1. 用户的请求提交给控制器

  2. 控制器接收到用户请求后根据用户的具体需求 调用相应的程序来处理用户的请求

  3. 控制器调用程序处理完数据后 将数据显示出来

  // 定义模型 按照要求读取数据
  class Model 
    m1() 
      return \'Model1\';
    
    m2() 
      return \'Model2\';
    
  

  // 定义视图 用于数据展示
  class View 
    v1(m) 
      console.log(m);
    
    v2(m) 
      document.write(m);
    
  

  // 根据控制器找到对应数据
  class Control 
    constructor() 
      this.m = new Model();
      this.v = new View();
    
    c1() 
      let value = this.m.m1();
      this.v.v1(value);
    
    c2() 
      let value = this.m.m2();
      this.v.v2(value);
    
  

  // 创建一个控制器实例对象
  const c = new Control();

  // 发出指令
  c.c1();
  c.c2();

9. 组合模式

概念 :

把多个对象组成树状结构来表示局部与整体,使得用户可以同时操作单个对象或对象的组合

优点 :

  • 组合模式可以非常方便地描述对象部分-整体层次结构
  • 组合模式将一批子对象组织为树形结构 一条根命令能操作下面所有子元素
  // <style>
  //   imgwidth:100px;
  //   *margin: 10px;padding: 10px;
  // </style>

  // 枝
  class Team 
    constructor(id) 
      // 组合模式核心之一 使得每个元素都能保存自己所有的子元素
      this.children = [];
      this.ele = document.createElement(\'div\');
      this.ele.id = id;
    
  
    add(child) 
      // 在数组中加入child元素
      this.children.push(child);
      // 将child添加到当前实例对象对应元素(this.ele)中
      this.ele.appendChild(child.ele);
    

    remove(child) 
      // 找到这个child元素在数组中索引
      let c = this.children.indexOf(child);
      // 根据索引删除元素
      this.children.splice(c, 1);
      // child为实例对象 找到实例对象对应元素 并删除节点元素
      child.ele.remove();
    

    addBorder() 
      // 给当前实例对象对应元素添加边框
      this.ele.style.border = \'2px solid black\';
      // 以下递归和核心之一
      // 给当前实例对象children数组(保存所有子元素对应实例对象)中所有元素也添加边框 如果子实例对象对应实例对象中还有实例对象则递归进去 重复之前步骤 直到所有子孙元素
      this.children.forEach(val => val.addBorder());
    

    removeBorder() 
      // 给当前实例对象对应元素删除边框
      this.ele.style.border = \'none\';
      // 原理同addBorder
      this.children.forEach(val => val.removeBorder());
    
  

  // 叶
  class Item 
    constructor(src) 
      // 此处ele为核心之一 这里的ele必须和上面枝中的ele相同 如果不同 this.ele在递归到叶中实例对象时 因找不到ele元素而报错而报错
      this.ele = document.createElement(\'img\');
      this.ele.src = src;
    
    add() 
      console.log(\'此为叶节点 不能添加\');
    
    remove() 
      console.log(\'此为叶节点 不能删除\');
    
    addBorder() 
      // 叶没有子元素 所以只要给自己添加边框
      this.ele.style.border = \'2px solid red\';
    
    removeBorder() 
      // 叶没有子元素 所以只要给自己删除边框
      this.ele.style.border = \'none\';
    
  

  // 创建叶实例对象
  const img1 = new Item("https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF");
  const img2 = new Item("https://t7.baidu.com/it/u=4198287529,2774471735&fm=193&f=GIF");
  const img3 = new Item("https://t7.baidu.com/it/u=2511982910,2454873241&fm=193&f=GIF");
  const img4 = new Item("https://t7.baidu.com/it/u=3435942975,1552946865&fm=193&f=GIF");

  // 创建枝对象
  const box1 = new Team("box1");
  const box2 = new Team("box2");
  const box3 = new Team("box3");
  const box4 = new Team("box4");
  const box5 = new Team("box5");

  // 将盒子 和 img组合
  box1.add(box2);
  box1.add(box3);
  box3.add(box4);
  box4.add(box5);

  box1.add(img1);
  box4.add(img2);
  box4.add(img3);
  box5.add(img3);

  // 以下为box在body中排列
    //   box1
    //     box2
    //     box3
    //       box4
    //         box5
              // img3
          //   img2
          //   img3
          // img1

  // 将根box1添加到body中
  document.body.appendChild(box1.ele);

  // 给元素添加删除边框
  box1.addBorder();
  box3.addBorder();

  img2.removeBorder();

javascript命令行为设计模式(代码片段)

查看详情

javascript国家行为设计模式(代码片段)

查看详情

javascript访客行为设计模式(代码片段)

查看详情

javascript单身创造设计模式(代码片段)

查看详情

javascript状态模式示例(javascript)(代码片段)

查看详情

javascript承诺模式(代码片段)

查看详情

javascript模块模式(代码片段)

查看详情

javascript责任链行为设计模式(代码片段)

查看详情

javascript抽象工厂创作设计模式(代码片段)

查看详情

javascript模板方法行为设计模式(代码片段)

查看详情

javascript迭代器行为设计模式(代码片段)

查看详情

javascript立面结构设计模式(代码片段)

查看详情

javascript桥梁结构设计模式(代码片段)

查看详情

javascript复合结构设计模式(代码片段)

查看详情

javascript代理结构设计模式(代码片段)

查看详情

javascript装饰结构设计模式(代码片段)

查看详情

javascript【设计模式】观察者模式(代码片段)

查看详情

javascript观察者行为设计模式(代码片段)

查看详情