JavaScript设计模式——工厂模式

2023-11-06

  在介绍工厂模式之前,首先我们要理解一下什么是设计模式?什么是设计原则?

  设计模式:

    通常在我们解决问题的时候,很多时候不是只有一种方式,我们通常有多种方式来解决;但是肯定会有一种通用且高效的解决方案,这种解决方案在软件开发中我们称它为设计模式;

    设计模式并不是一种固定的公式,而是一种思想,是一种解决问题的思路;恰当的使用设计模式,可以实现代码的复用和提高可维护性;

  设计原则:

    通常在做很多事情的时候,都会有一定的规范制约;在软件开发的过程中,我们可以将设计原则视为一种开发规范,但不是必须要遵循的,只是不遵循的话,代码后期的维护和复用都会变得很糟糕;

    遵循设计原则可以帮助我们写出高内聚、低耦合的代码,当然代码的复用性、健壮性、可维护性也会更好;

 

  有哪些设计模式:

    在程序设计中我们通常认为是有23种设计模式,根据分类分别为:

   创建型:

  1. 抽象工厂模式  
  2. 工厂方法模式
  3. 建造者模式
  4. 原型模式
  5. 单例模式(又称单体模式)

   结构型:

  1. 适配器模式
  2. 桥接模式
  3. 组合模式
  4. 装饰者模式
  5. 外观模式
  6. 享元模式
  7. 代理模式

  行为型:

  1. 职责链模式
  2. 命令模式
  3. 解释器模式
  4. 迭代器模式
  5. 中介者模式
  6. 备忘录模式
  7. 观察者模式(又称发布/订阅模式)
  8. 状态模式
  9. 策略模式
  10. 访问者模式
  11. 模板方法模式 

  有哪些设计原则:

    根据英文首单词我们又称为S.O.L.I.D.设计原则,一共有5种设计原则,根据分类分别为:

    1、S(Single responsibility principle)——单一职责原则

    一个程序或一个类或一个方法只做好一件事,如果功能过于复杂,我们就拆分开,每个方法保持独立,减少耦合度;

    2、O(Open Closed Principle)——开放封闭原则

    对扩展开放,对修改封闭;增加新需求的时候,我们需要做的是增加新代码,而非去修改源码;

    例如:我们在使用vue框架的时候,有很多第三方插件我们可以去使用,在使用的时候我们通常都是直接在vue-cli中增加引入代码,而非去修改vue源码来达到支持某种功能的目的;

    3、L(Liskov Substitution Principle, LSP)——李氏置换原则

    子类能覆盖父类,父类能出现的地方子类就能出现;(在JS中没有类概念,使用较少)

    4、I (Interface Segregation Principle)——接口独立原则

    保持接口的单一独立,类似于单一原则,不过接口独立原则更注重接口;(在JS中没有接口概念)

    5、D(Dependence Inversion Principle ,DIP)——依赖倒置原则

    面向接口编程,依赖于抽象而不依赖于具体,使用方只关注接口而不需要关注具体的实现;(JS中没有接口概念)

 

    作为前端开发人员来说,我们用的最多的设计原则是S(单一职责原则).O(开放封闭原则),所以在程序设计的时候我们重点关注这两个即可 ;

 

    设计模式——工厂模式:

      所谓工厂模式就是像工厂一样重复的产生类似的产品,工厂模式只需要我们传入正确的参数,就能生产类似的产品;

      工厂模式根据抽象程度依次分为简单工厂模式、工厂方法模式、抽象工厂模式;

    简单工厂模式:

    在我们的生活中很多时候就有这样的场景,像在网站中有的页面是需要根据账号等级来决定是否有浏览权限的;账号等级越高可浏览的就越多,反之就越少;

    // JS设计模式之简单工厂
    function factory(role){
        function superAdmin(){
            this.name="超级管理员";
            this.viewPage=["首页","发现页","通讯录","应用数据","权限管理"];
        }

        function admin(){
            this.name="管理员";
            this.viewPage=["首页","发现页","通讯录","应用数据"];
        }

        function user(){
            this.name="普通用户";
            this.viewPage=["首页","发现页","通讯录"];
        }

        switch(role){
            case "superAdmin":
                return new superAdmin();
                break;

            case "admin":
                return new admin();
                break;
            
            case "user":
                return new user();
                break;
        }
    }

    let superAdmin = factory("superAdmin");
    console.log(superAdmin);
    let admin = factory("admin");
    console.log(admin);
    let user = factory("user");
    console.log(user);

  上述代码中,factory就是一个工厂,factory有三个函数分别是对应不同的产品,switch中有三个选项,这三个选项相当于三个模具,当匹配到其中的模具之后,将会new一个构造函数去执行生产工厂中的function;但是我们发现上面的简单工厂模式会有一定的局限性,就是如果我们需要去添加新的产品的时候,我们需要去修改两处位置(需要修改function和switch)才能达到添加新产品的目的;

  下面我们将简单工厂模式进行改良:

  

    // JS设计模式之简单工厂改良版
    function factory(role){
        function user(opt){
            this.name = opt.name;
            this.viewPage = opt.viewPage;
        }

        switch(role){
            case "superAdmin":
                return new user({name:"superAdmin",viewPage:["首页","发现页","通讯录","应用数据","权限管理"]});
                break;

            case "admin":
                return new user({name:"admin",viewPage:["首页","发现页","通讯录","应用数据"]});
                break;

            case "normal":
                return new user({name:"normal",viewPage:["首页","发现页","通讯录"]});
        }
    }

    let superAdmin = factory("superAdmin");
    console.log(superAdmin);
    let admin = factory("admin");
    console.log(admin);
    let normal = factory("normal");
    console.log(normal);

  经过上面的修改之后,我们工厂里面的函数相当于一个万能摸具,switch里面给我什么,我就加工成什么样的;自然就解决了添加商品需要修改两处代码的问题;

 

  工厂方法模式:

    工厂方法模式是将创建对象的工作推到子类中进行;也就是相当于工厂总部不生产产品了,交给下辖分工厂进行生产;但是进入工厂之前,需要有个判断来验证你要生产的东西是否是属于我们工厂所生产范围,如果是,就丢给下辖工厂来进行生产,如果不行,那么要么新建工厂生产要么就生产不了;

    // JS设计模式之工厂方法模式
    function factory(role){
        if(this instanceof factory){
            var a = new this[role]();
            return a;
        }else{
            return new factory(role);
        }
    }

    factory.prototype={
        "superAdmin":function(){
            this.name="超级管理员";
            this.viewPage=["首页","发现页","通讯录","应用数据","权限管理"];
        },
        "admin":function(){
            this.name="管理员";
            this.viewPage=["首页","发现页","通讯录","应用数据"];
        },
        "user":function(){
            this.name="普通用户";
            this.viewPage=["首页","发现页","通讯录"];
        }
    }

    let superAdmin = factory("superAdmin");
    console.log(superAdmin);
    let admin = factory("admin");
    console.log(admin);
    let user = factory("user");
    console.log(user);

  工厂方法模式关键核心代码就是工厂里面的判断this是否属于工厂,也就是做了分支判断,这个工厂只做我能生产的产品,如果你的产品我目前做不了,请找其他工厂代加工;

 

  抽象工厂模式:

    如果说上面的简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的;

    举个例子:代理商找工厂进行合作,但是工厂没有实际加工能力来进行代加工某产品;无奈又签署了合同,这时,工厂上面的集团公司就出面了,集团公司承认该工厂是该集团下属公司,所以集团公司就重新建造一个工厂来进行代加工某商品以达到履行合约;

        //JS设计模式之抽象工厂模式
        let agency = function(subType, superType) {
      //判断抽象工厂中是否有该抽象类
      if(typeof agency[superType] === 'function') {
        function F() {};
        //继承父类属性和方法
        F.prototype = new agency[superType] ();
        console.log(F.prototype);
        //将子类的constructor指向子类
        subType.constructor = subType;
        //子类原型继承父类
        subType.prototype =  new F();
    
      } else {
        throw new Error('抽象类不存在!')
      }
    }
    
    //鼠标抽象类
    agency.mouseShop = function() {
      this.type = '鼠标';
    }
    agency.mouseShop.prototype = {
      getName: function(name) {
        // return new Error('抽象方法不能调用');
        return this.name;    
      }
    }
    
    //键盘抽象类
    agency.KeyboardShop = function() {
      this.type = '键盘';
    }
    agency.KeyboardShop.prototype = {
      getName: function(name) {
        // return new Error('抽象方法不能调用');
        return this.name;
      }
    }
    
    
    
    //普通鼠标子类
    function mouse(name) {
      this.name = name;
      this.item = "买我,我线长,玩游戏贼溜"
    }
    //抽象工厂实现鼠标类的继承
    agency(mouse, 'mouseShop');
    //子类中重写抽象方法
    // mouse.prototype.getName = function() {
    //   return this.name;
    // }
    
    //普通键盘子类
    function Keyboard(name) {
      this.name = name;
      this.item = "行,你买它吧,没键盘看你咋玩";
    }
    //抽象工厂实现键盘类的继承
    agency(Keyboard, 'KeyboardShop');
    //子类中重写抽象方法
    // Keyboard.prototype.getName = function() {
    //   return this.name;
    // }
    
    
    
    //实例化鼠标
    let mouseA = new mouse('联想');
    console.log(mouseA.getName(), mouseA.type,mouseA.item); //联想 鼠标
    
    //实例化键盘
    let KeyboardA = new Keyboard('联想');
    console.log(KeyboardA.getName(), KeyboardA.type,KeyboardA.item); //联想 键盘

  抽象工厂模式一般用于严格要求以面向对象思想进行开发的超大型项目中,我们一般常规的开发的话一般就是简单工厂和工厂方法模式会用的比较多一些;

大白话解释:简单工厂模式就是你给工厂什么,工厂就给你生产什么;

             工厂方法模式就是你找工厂生产产品,工厂是外包给下级分工厂来代加工,需要先评估一下能不能代加工;能做就接,不能做就找其他工厂;

      抽象工厂模式就是工厂接了某项产品订单但是做不了,上级集团公司新建一个工厂来专门代加工某项产品;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript设计模式——工厂模式 的相关文章

随机推荐

  • 电商平台商品爬虫+django可视化分析

    1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目 电商平台商品爬虫 django可视化分析 计算机毕业生设计 课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代 随着信息技术和网络技术的发展 信息化已经渗透到人们日常生
  • GinCMS 使用golang Gin框架xorm开发的小型内容管理系统

    系统介绍 服务器端 使用GoLang 基于Gin框架 MySQL数据库 用到的组件xorm 前端展示 使用基于LayUI的layuicms 用到的第三方组件authtree treeTable GinCMS是我学习golang 使用Gin开
  • hdu 1210 Eddy's 洗牌问题

    题目连接 http acm hdu edu cn showproblem php pid 1210 题目思路很简单 只要保证1在第一个位置的时候就说明牌的顺序达到要求 输出M就可以了 代码 include
  • Unity3d——UI(血条制作)

    血条 Health Bar 制作 具体要求如下 分别使用 IMGUI 和 UGUI 实现 使用 UGUI 血条是游戏对象的一个子元素 任何时候需要面对主摄像机 分析两种实现的优缺点 IMGUI 效果图 血条红色不是很明显 为了显示IMGUI
  • python包安装相关-conda,pip-虚拟环境

    运行python的时候一定要注意当前运行所在环境位置 环境位置不同 包含的依赖包是不同的 然后不注意的话就是出很多莫名其妙的问题 比如一个pycharm里面不能运行的东西 命令行又能运行啥的 PIP使用的一些点 pip安装包的时候加上后缀
  • 7.4.3-elasticsearch索引字段类型参数

    fielddata 大多数字段默认情况下都会建立索引方便查询 但是针对排序 聚合以及脚本访问字段值则需要另外的访问方式 查询操作需要回答 哪些doc包含查询的词 而排序和聚合则需要回答 doc中该字段的值是多少 大多数字段可以通过文档索引在
  • linux grep命令

    1 作用 Linux系统中grep命令是一种强大的文本搜索工具 它能使用正则表达式搜索文本 并把匹 配的行打印出来 grep全称是Global Regular Expression Print 表示全局正则表达式版本 它的使用权限是所有用户
  • maven中mirror镜像和repository仓库配置

    maven仓库和镜像配置 1 名词解释 2 reportsitory仓库配置 3 mirror镜像配置 4 mirror与reporsitory 4 1 mirror与reporsitory的关系 4 2 mirrorOf的作用 1 名词解
  • Deveco studio 鸿蒙app访问网络详细过程(js)

    目录 效果图 安装IDE工具Deveco studio 创建项目 项目配置 编辑 功能开发 效果图 话不多说 上效果 安装IDE工具Deveco studio 下载地址 HUAWEI DevEco Studio和SDK下载和升级 Harmo
  • vue2如何使用element ui快速搭建自己的前端页面

    文章目录 前言 一 element ui是什么 二 使用步骤 1 在项目中引入 element ui 2 全局引入 element ui 组件 3 局部引入 element ui 组件 4 使用组件 前言 element ui 是一款非常好
  • 使用pyecharts绘制系统依赖关系图

    使用pyecharts绘制系统依赖关系图 背景介绍 近期梳理了公司内部系统之间的数据关系 得到了多个excel格式的统计文件 每个文件包含了该系统自身数据清单 依赖的其他系统的数据清单 对其他系统供应的数据清单 各系统之间依赖关系复杂 所以
  • 【Tomcat】Tomcat配置ssl证书

    记一次因各种需求在Linux中配置tomcat的https自签发证书过程 SSL证书简介 1 公开可信认证机构 例如CA 但是申请一般是收费的 一般几百到几千一年 在这里可以给你们介绍一下腾讯云截止到目前还有免费一年的CA证书服务 可以用一
  • 第三方服务器不在响应,服务器是怎样响应请求的?

    小弟最近在改后端项目 但出了个 bug 又解决不了 我觉得是我的后端知识太欠缺了 特来这里请教 流程是这样的 前端有上送信息 接口收到信息后 用收到的部分信息再去第三方接口请求信息 把两部分合起来存储 收到的信息中有一部分是用户ID 绝不重
  • Java: StringBuffer类的运用

    字符串的学习不比其他数据类型的学习 不管是对对象 对象的实体 属性等 的打印 还是在平常所有可以展示出来供我们进行参考的数据内容 共同点就是它们都是 string 字符串 都是一种字符串文本 而且在对一些我们所想表达的数据的提交和获取时 都
  • DBA的一些职责

    1 DBA的一些职责 安装和升级数据库服务器 如Oracle Microsoft SQL server 以及应用程序工具 数据库设计系统存储方案 并制定未来的存储需求计划 一旦开发人员设计了一个应用 就需要DBA来创建数据库存储结构 tab
  • DNN结构:CNN、LSTM/RNN中的Attention结构

    前言 attention作为一种机制 有其认知神经或者生物学原理 注意力的认知神经机制是什么 如何从生物学的角度来定义注意力 大多数attention gating 技巧都可以直接加入现有的网络架构 通过合理设计初始化和训练步骤也可以利用现
  • Linux--写时拷贝、内存管理

    目录 1 内存管理 2 写时拷贝技术 1 内存管理 简单分页 逻辑页 物理页 页表 将虚拟内存空间和物理内存空间划分为大小相同的页面 4k 8k 16k等 虚拟内存 在磁盘上划分一块空间 为什么要有逻辑页面和物理页面 物理页面很长 不能确定
  • ubuntu 设置网络代理

    Ubuntu下通过终端设置网络代理 以便apt get等命令可以正常使用 只需在终端里设置http proxy系统变量即可 plain export http proxy http usr name usr password ipaddre
  • 华为云交付项目服务器配置表,云服务器设备配置列表

    云服务器设备配置列表 内容精选 换一换 当您在华为云上部署了弹性云服务器以及其他云服务 想在关联VPC内通过内网域名实现互访 可以为弹性云服务器配置内网域名解析 内网域名可以随意创建 无需注册 只需要保证VPC内唯一 本操作以为弹性云服务器
  • JavaScript设计模式——工厂模式

    在介绍工厂模式之前 首先我们要理解一下什么是设计模式 什么是设计原则 设计模式 通常在我们解决问题的时候 很多时候不是只有一种方式 我们通常有多种方式来解决 但是肯定会有一种通用且高效的解决方案 这种解决方案在软件开发中我们称它为设计模式