JavaScript设计模式
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: 控制器 向系统发出指令的工具
优点
- 降低代码耦合
- 分工合作 提高开发效率
- 组件重用
工作流程
用户的请求提交给控制器
控制器接收到用户请求后根据用户的具体需求 调用相应的程序来处理用户的请求
控制器调用程序处理完数据后 将数据显示出来
// 定义模型 按照要求读取数据 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. 组合模式
概念 :
把多个对象组成树状结构来表示局部与整体,使得用户可以同时操作单个对象或对象的组合
优点 :
- 组合模式可以非常方便地描述对象部分-整体层次结构
- 组合模式将一批子对象组织为树形结构 一条根命令能操作下面所有子元素
// // 枝 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设计模式
- 环球关注:怪盗基德在名侦探柯南出场集数片段_怪盗基德在名侦探柯南出场集数
- 全球观天下!一批大项目提速开工 稳投资“扬鞭”加力
- 一批大项目提速开工 稳投资“扬鞭”加力
- 交通银行电子对账系统(交通银行网上电子对账系统)|天天动态
- 成都国色天乡童话乐园五一童话马戏节门票+演出时刻表
- 洛杉矶旅游攻略附带详细路线图_洛杉矶旅游攻略|当前快看
- 反者道之动蕴含的辩证法是什么_反者道之动蕴含的辩证法是
- 顶点软件:2023年第一季度净利润约2214万元
- 法比奥:多一人但整体控制做得不好,本赛季我们一直会面对压力
- 海安市白甸镇:读书,遇见更好的自己-世界播报
- 环球最新:2天订单破10000台, 比亚迪海鸥将上市,5门4座,续航405km
- 当前信息:上海:“五一”假期外滩等地区不展演主题光影秀
- 第四届中国青年马克思主义大会在电子科技大学召开
- 天天快资讯丨锡东新城吧2018_无锡锡东新城吧
- 2023年郑州中原区百货消费券怎么使用?附使用规则_微资讯
- 每日简讯:央行公布3月金融市场运行情况:沪市日均交易量环比增加10.4%
- 网页模式极速改成兼容 极速模式怎么改成兼容模式_全球热议
- 关注森林,衡阳收获亮眼“绿色成绩单”-每日播报
- 公寓没租出去,想解约得付八千,律师提了一个建议
- 1环球今日讯!告示范文英语_告示范文
- 2天天即时看!铜库存
- 3玉树施工合同律师费一般是多少 每日速讯
- 4【大国基理】背包法庭创新做法 把法庭“背到”人民群众家门口-天天看热讯
- 5当前看点!省教育厅:今年新增50个产业急需的新兴重点专业
- 6实时焦点:花小猪开放平台:中小商家订单量涨幅超1倍
- 7五一出行遇“酒店刺客”?民宿临时涨价,违约也要“赶客”|全球最资讯
- 8需求难有实质提升 短线醋酸市场清淡运行-焦点热讯
- 9天天观天下!头“顶”的毛发生意值钱吗?
- 10关注:特色产业硕果飘香
- 1孙新军主持召开区委人才工作领导小组会议,强调要发挥人才引领驱动作用,打响东城人才工作品牌 天天新消息
- 2民宿想当“刺客”,法律就应为铠甲
- 31万一个月扣多少个税_深圳市个人所得税计算方法-世界微头条
- 4又一世界第一!“氢风”已至!加油站纷纷出手布局
- 5湖南化工职院领导率队开展访企拓岗促就业专项行动_天天聚看点
- 6世界观速讯丨大白菜U盘重装win10系统教程
- 7航民股份(600987):4月24日北向资金增持30.64万股|环球通讯
- 8天天资讯:岭南股份(002717):4月24日北向资金增持213.3万股
- 9好看的古装电视剧修仙_好看的古装电视剧
- 10当前快讯:星辉娱乐:通过第三方软件推进实施AI技术的应用 并不直接拥有相关技术
广告
- 图解金刚光伏年报:第四季度单季净利润同比增43.64%|当前热点
- 青岛啤酒单季营收再创新高 一季度盈利增长近三成
- 环球短讯!圣龙股份: 圣龙股份2022年年度利润分配预案的公告
- 要闻速递:渭滨区气象台发布霜冻蓝色预警【Ⅳ级/一般】【2023-04-24】
- 最高可贷150万!这个省调整住房公积金政策
- 西部牧业2022年营收13.25亿 净利1298.48万 董事长李昌胜薪酬13万
- 金马游乐:特种设备对产能性能、安全等级等有较高要求
- 美方要求韩企不要填补美光在华市场缺口 中方:典型的科技霸凌 天天热门
- 世界快播:51mh官网是多少(51mh.ifnocc官方版入口)
- 重返未来1999冬值得培养吗 木系角色冬技能解析_天天热点评
- 北京发布五一假期文旅系列活动 丰富市民游客旅游生活_当前视点
- 每日简讯:本周国内异丁醛价格上涨0.22%(4.17-4.23)
- 十九年十九城一一上交所ETF宣介会嘉实基金专场4月22日成功举办_环球关注
- 世界今日讯!2023上海车展大奖:种草后就能买 车展最佳即将上市车型有哪些?
- 浙闽赣皖4城发布倡议 打造成果转移转化共同体-环球即时
- 东方电子集团董事长、总经理杨恒坤被查
- 《新仙剑奇侠传之挥剑问情》赤鬼王高分攻略
- 宣武区离婚财产分割律师收费最新标准
- 全球速递!扬电科技(301012)4月24日主力资金净卖出14.38万元
- 盈珑操盘(淘宝退款几天到账)|环球新要闻