前言

设计模式不容易用文字描述清楚,而过多的代码,看起来也让人摸不到头脑,加上词语或者文字描述的抽象感,很容易让人看了无数设计模式的文章,也仍然理解不了。 所以我一直打算写此系列博客,首先我会从大量文章里去理解这些设计模式,最后我用自己的语言组织转化为博客,希望用更少的代码,更容易理解的文字,来聊一聊这些设计模式。 我所理解、所描述的每一个设计模式也可能有些是错误的,甚至也不一定有非常深刻的理解,所以希望有人指出,我可以更改博客内容。 我作为前端开发者,所以设计模式的代码以前端代码和视角为主。 此博客内容对每一种模式并不会写得非常深入,也许能为读者打通一些认知,如果看了此系列博客,再去看其他更深入的博客,可能是一种比较好的方式。

代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

生活中的例子:买火车票不一定在火车站买,也可以去代售点或者网上购买,vpn。

常见的代理模式应用例子:前后端交互,往往后端有server层和应用层,前端只和后端应用层打交道,应用层调取server层,server层职责单一,应用层处理逻辑。 应用层既是代理层,也可以叫中间件。

代理模式最开始我一直没有想到平时前端应用中的例子。但是经过多次推敲和联系,发现代理模式的使用无处不在,再读一遍描述(在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。)。那么我认为对API的封装可以算是代理模式的应用,一般对API进行封装,肯定是希望在调用API的时候做一些通用的事情或者处理,以便让对象的调用更方便或者更适应业务。比如我们要封装一下js的location.href的跳转。我们想在跳转之前进行一些统计,那么我们可以在location.href前处理跳转逻辑。但是因为要跳转的地方太多了,我不想每个地方都有跳转逻辑,所以我封装一个jump方法,专门处理跳转,并在跳转之前处理统计逻辑。而后我在跳转前还需要做其他事情,就可以直接在这个jump方法里实现,扩展性也非常高。

function jump(url){//统计逻辑location.href = url;
}
jump('baidu.com')
复制代码

优点:

  • 职责清晰
  • 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
  • 高扩展性

缺点:

  • 会使程序处理和响应速度变慢

中介者模式

中介者模式是用来降低多个对象和类之间的交互复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的交互,并支持松耦合,使代码易于维护。 中介者模式属于行为型模式。

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,形成网状结构。

典型应用例子:MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。

相信现在的框架模式至少都是mvc或者mvvm。我曾经看过一个运行的老项目.net代码,一个aspx文件中写了html,css,js,.net,并且数据库查询操作也写到页面中了,那页面维护起来就非常酸爽了。 如果使用mvc模式,控制器作为中介,隔离model和view让它们不直接交互,达到了解耦效果,虽然会增加代码量,但是交互的可重用性得到了提升,代码复杂度降低,逻辑更加清晰,更易于维护,也就是所谓高内聚低耦合。

现实中的例子:在学校下发一个通知的时候,如果是通过口口相传的方式,那么学生之间的关系是多对多的关系,非常难以准确传达到每个人手里。如果学校贴一张公告单到校门口,那么公告单作为学校和学生的中介,就能让关系变得简单。我们平时生活中的聊天群也可以达到同样效果。网状结构的关系由此变成了星型结构。如下盗图:

观察者模式

观察者模式(有时又被称为发布-订阅模式)是设计模式的一种。 在此种模式中, 一个或者多个观察者去监听主题,当主题发生变化的时候,主题会通知所有的观察者。 这通常透过调用观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。 比如常用的事件监听,onclick,onload等。

vue采用数据劫持结合观察者模式,通过Object.defineProperty方法来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的回调。 写一个删减版的类似例子(直接复制代码在控制台运行试试):

function Observer(data){//传入观察对象this.data = data;this.defineReactive(data);
}Observer.prototype = {defineReactive: function(data){var self = this;var dep = new Dep();dep.addSub(data);//添加订阅Object.keys(data).forEach(function(key){var val = data[key];Object.defineProperty(data, key, {get: function(){return val;},set: function(newVal){if(val == newVal) return;val = newVal;dep.notify();//发生改变下发通知}})})}
}function Dep(){}
Dep.prototype = {addSub: function(sub){this.sub = sub;},notify: function(){console.log(this.sub);//当前对象有值的改变,打印出当前对象}
}var data = {val: 1
}
new Observer(data);
data.val = 2;//执行后,在控制台会打印出当前对象,直接复制这段代码运行试试复制代码

策略模式

  • 定义了一系列算法;
  • 封装了每个算法;
  • 这一系列的算法可互换代替。

策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换,让算法仅仅只做算法,让其它逻辑的事情交给策略类去处理。 下面直接用例子说明。

我们常会封装一个验证工具类,一般的写法是定义一个对象字面量,不同的属性定义不同的验证方法,大致如下代码:

var validator = {isNumber:function(val){if(false) alert('非法数字');//return true or false},isPhone:function(){}//.....
}复制代码

这样在使用和维护验证的时候,重复代码量会比较多,一个验证方法需要处理验证算法和验证后的逻辑(验证返回、提醒等),不管提醒是写在验证方法内还是在外部方法外,这些逻辑每次都要处理一次。 那么使用策略类,来统一处理验证逻辑,并把验证算法独立开,这样之后维护只修改和添加算法方法。 那么怎么做呢,如下代码:

var validator = {validate: function(type, val){for (prop in this.types) {if(type == prop){//调用对应验证方法var result = this.types[type].validate(val);if(!result) alert(this.types[type].text);return result;}}},types: {//定义验证算法isNumber:{validate: function(val){//判断return true or false;},text: '非法数字'},isPhone:function(){}//.....  }
}var input1 = $('input').val();
validator.validate('isNumber', input1)复制代码

以上代码只是一个小demo,并不完善,想表达的意思就是策略模式,把算法和策略类独立开来,根据需求算法可以替换,策略类统一处理。 angular的验证类FormGroup就使用了这一模式。 上面的demo因为还比较简单,所以一下感觉不到有多大差别,但是如果你真正使用过类型angular的FormGroup这类的验证方式,你就会发现能节省很多代码量,逻辑也非常清晰。

状态模式

允许一个对象在其内部状态改变时改变它的行为。 对象看起来似乎修改了它的类。通俗的说,对象内部定义了不同状态的类,在状态改变的时候,替换对象相应的类。

举一个生活中的例子:当我们的手机电量比较充足的时候,手机会使用正常模式用电,当电量小于20%的时候,手机会使用省电模式。电量就是状态,正常模式和省电模式就是相应的替换类。

再举一个前端的例子: 博客园的后台首页右上角,有两种形态,一种是登录之后,会显示当前用户名和注销按钮,一种是没有登录会展示登录按钮和注册按钮。 假如博客园使用了双向绑定, 那么在模板里,会有登录和未登录的html代码,然后通过一个指令(比如ngShow)传入控制器变量操作谁隐藏谁显示。 那么控制器的变量就是状态,登录和未登录模板代码就是状态对应的类。 这个模式我想作为前端肯定是会常常使用的。所以此模式就不用代码描述了。

此系列博客目录:

子慕谈设计模式系列(一)
子慕谈设计模式系列(二)——设计模式六大原则
子慕谈设计模式系列(三)

子慕谈设计模式系列(三)相关推荐

  1. 子慕谈设计模式系列(二)——设计模式六大原则

    六大原则 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 前言 设计模式不容易用文字描述清楚,而过多的代码,看起来也让人摸不到头脑,加上词语或者文字描述的抽象感,很容易让 ...

  2. 设计模式系列——三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)...

    转自:http://www.cnblogs.com/stonehat/archive/2012/04/16/2451891.html 设计模式系列--三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂 ...

  3. Javascript乱弹设计模式系列(1) - 观察者模式(Observer)

    前言 博客园谈设计模式的文章很多,我也受益匪浅,包括TerryLee.吕震宇等等的.NET设计模式系列文章,强烈推荐.对于我,擅长于前台代码的开发,对于设计模式也有一定的了解,于是我想结合Javasc ...

  4. 设计模式系列-代理模式

    为什么80%的码农都做不了架构师?>>>    一.上篇回顾 很久没有更新设计模式系列的文章了,有了很多热心朋友的反馈,我决定继续将这个系列赶快写完,最近由于过年了,有很多相关的事宜 ...

  5. JavaScript设计模式系列—模式篇总结(上)

    转载请注明预见才能遇见的博客:http://my.csdn.net/ 原文地址:https://blog.csdn.net/pcaxb/article/details/102517956 JavaSc ...

  6. PHP - 设计模式系列

    1.应用场景 主要用于学习掌握编程中的设计模式,开发高质量, 易扩展,维护的程序. 学习掌握编程最佳实践.有时候也是为了应对面试,但不应该是作为有追求的编程者的主要目的. 2.学习/操作 1.文档阅读 ...

  7. 设计模式(三)结构型模式介绍及实例

    文章目录 一.适配器模式 1.1 适配器模式定义 1.2 适配器模式主要角色 1.3 适配器模式特点 1.4 适配器模式实现方式 1.4.1 类适配器模式 1.4.2 对象适配器模式 1.5 适配器模 ...

  8. 设计模式系列之 模板方法模式

    定义 在模板方法中定义一个算法的骨架,而将部分步骤延迟到子类中,使子类在不改变算法结构的情况下,重新定义算法中的部分步骤. 理解该模式的关键就在"模板"二字.什么是模板?模板就是预 ...

  9. 在深谈TCP/IP三步握手四步挥手原理及衍生问题—长文解剖IP

    如果对网络工程基础不牢,建议通读<细说OSI七层协议模型及OSI参考模型中的数据封装过程?> 下面就是TCP/IP(Transmission Control Protoco/Interne ...

  10. 刚子扯谈:谢谢你 要学会尊重文字 即使它写的很狗屎

    文/刚子 2013年7月27日 北京的天总是变化多端,突然觉得这就跟女人一样,当然这个比喻不是很对.吓扯谈吧! 今天主要想表达感激,感激我在即将过去的7月,在7月的某天我重拾CSDN账号,把原有的博客 ...

最新文章

  1. 前沿丨人工智能的框架战争:FB继续挑战Google
  2. 8个试剂,其中一个有毒,最少多少只小白鼠能检测出有毒试剂——分而治之思想...
  3. java代码,输入n多个数,求其平均值,虽有重复,但是第二次,我就乱写了
  4. java统计一个字符串中每个字符出现的次数_剑指offer算法题054:字符流中第一个不重复的字符...
  5. 不允许后退提交数据的方法(抗重复刷新提交)
  6. 解决bbb无法加载uImage问题
  7. WinXP下变量方式表达对应路径说明
  8. 面积积分_袁颖妍:用定理积分求平面区域面积(有代表性的9个例题)
  9. 史上最全PostgreSQL体系结构
  10. 【C++笔记】变量和基本类型
  11. qq表情左右滑动php,基于jQuery实现的QQ表情插件_jquery
  12. 安卓火狐浏览器wifi远程调试没有扫描二维码应用的问题
  13. linux下查看vnc端口_Linux的VNCServer的默认端口是多少?
  14. 一图看尽APP各推广渠道“超级用户浓度”| 互联网行业公会
  15. 企业电子招投标系统简介 招投标系统源码 定制化服务 二次开发 java招投标系统 招投标系统功能设计
  16. Shell-01Shell初相识
  17. 【数据采集平台】教程-单页面采集
  18. css文件插入背景音乐,关注css背景音乐代码
  19. matlab_格兰杰因果关系检验
  20. 想学ui设计从哪里入手?基础怎么入门学习UI设计呢?

热门文章

  1. TVS 瞬态抑制二极管如何选型?
  2. java正方形个圆形面积_JAVA--接口练习(求正方形和圆的周长、面积)
  3. 美元MogaFX指数介绍(二)
  4. IP协议的详细知识总结
  5. leetcode845. 数组中的最长山脉
  6. Lumion 11学会像真正的专业人士一样渲染
  7. C语言pow函数返回值一直是0
  8. 网课答题查询助手(免费)
  9. spss进行相关性分析
  10. 路由器与交换机的作用及区别