设计模式的理解与举例
设计模式介绍
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
- 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
为什么要有设计模式?好处是什么?
- 为了重用代码、让代码更容易被他人理解、保证代码可靠性(设计模式提供了一个标准的术语系统,且具体到特定的情景)。
- 合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案。
设计模式分类
根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。
- 设计模式可以分为三大类:
- 创建型模式(Creational Patterns)
- 结构型模式(Structural Patterns)
- 行为型模式(Behavioral Patterns)
- 另一类设计模式:J2EE 设计模式
创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 过滤器模式(Filter、Criteria Pattern)
- 组合模式(Composite Pattern)
- 装饰器模式(Decorator Pattern)
- 外观模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 代理模式(Proxy Pattern)
行为型模式
这些设计模式特别关注对象之间的通信。
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 观察者模式(Observer Pattern)
- 状态模式(State Pattern)
- 空对象模式(Null Object Pattern)
- 策略模式(Strategy Pattern)
- 模板模式(Template Pattern)
- 访问者模式(Visitor Pattern)
J2EE 模式
这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
- MVC 模式(MVC Pattern)
- 业务代表模式(Business Delegate Pattern)
- 组合实体模式(Composite Entity Pattern)
- 数据访问对象模式(Data Access Object Pattern)
- 前端控制器模式(Front Controller Pattern)
- 拦截过滤器模式(Intercepting Filter Pattern)
- 服务定位器模式(Service Locator Pattern)
- 传输对象模式(Transfer Object Pattern)
设计模式之间的关系
具体设计模式举例
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
如下图的车,只有一辆,一旦借出去则不能再借给别人:
- 全局变量是单例模式吗?
- 一般情况我们不认为全局变量是一个单例模式,原因是:全局命名污染且不易维护,容易被重写覆盖。
- js中举例
- 在javascript中,实现一个单例模式可以用一个变量来标志当前的类已经创建过对象,如果下次获取当前类的实例时,直接返回之前创建的对象即可。
- 在前端中,很多情况都是用到单例模式,例如页面存在一个模态框的时候,只有用户点击的时候才会创建,而不是加载完成之后再创建弹窗和隐藏,并且保证弹窗全局只有一个。
- 现在很多第三方库都是单例模式,多次引用只会使用同一个对象,如jquery、lodash、moment…
工厂模式
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
- 工厂模式通常会分成3个角色:
- 工厂角色 — 负责实现创建所有实例的内部逻辑。
- 抽象产品角色 — 是所创建的所有对象的父类,负责描述所有实例所共有的公共接口。
- 具体产品角色 — 是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
就像工厂一样重复的产生类似的产品,工厂模式只需要我们传入正确的参数,就能生产类似的产品。
- 工厂模式根据抽象程度的不同可以分为:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
简单工厂模式(Simple Factory)
简单工厂模式也叫静态工厂模式,用一个工厂对象创建同一类对象类的实例。
- 假设我们要开发一个公司岗位及其工作内容的录入信息,不同岗位的工作内容不一致,当我们调用工厂函数时,只需要传递name、age、career就可以获取到包含用户工作内容的实例对象。
工厂方法模式(Factory Method)
跟简单工厂模式差不多,但是把具体的产品放到了工厂函数的prototype中。
- 相当于工厂总部不生产产品了,交给下辖分工厂进行生产。
- 但是进入工厂之前,需要有个判断来验证你要生产的东西是否是属于我们工厂所生产范围,如果是,就丢给下辖工厂来进行生产。
- 工厂方法关键核心代码是工厂里面的判断this是否属于工厂,也就是做了分支判断,这个工厂只做我能做的产品。
抽象工厂模式(Abstract Factory)
简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的。
- 由于JavaScript中并没有抽象类的概念,只能模拟,可以分成四部分:
- 用于创建抽象类的函数
- 抽象类
- 具体类
- 实例化具体类
策略模式
策略模式,就是定义一系列的算法,把他们一个个封装起来,目的就是将算法的使用与算法的实现分离开来,并且使他们可以相互替换。
- 至少分成两部分:
- 策略类(可变),策略类封装了具体的算法,并负责具体的计算过程。
- 环境类(不变),接受客户的请求,随后将请求委托给某一个策略类。
- 使用策略模式的优点有如下:
- 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句。
- 策略模式提供了开放 — 封闭原则,使代码更容易理解和扩展。
- 策略模式中的代码可以复用。
代理模式
代理模式:为对象提供一个代用品或占位符,以便控制对它的访问。
- 代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要时,提供一个替身对象来控制这个对象的访问,客户实际上访问的是替身对象。
- 在生活中,代理模式的场景是十分常见的,例如我们现在如果有租房、买房的需求,更多的是去找链家等房屋中介机构,而不是直接寻找想卖房或出租房的人谈。此时,链家起到的作用就是代理的作用。
- 例如实现图片懒加载的功能,先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。
实现
在ES6中,存在proxy构建函数能够让我们轻松使用代理模式:const proxy = new Proxy(target, handler);
按照功能来划分,javascript代理模式常用的有:
- 缓存代理
- 缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果。
- 虚拟代理
- 虚拟代理把一些开销很大的对象,延迟到真正需要它的时候才去创建,常见的就是图片预加载功能。
中介者模式
中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可
- 通过中介者模式可以解除对象与对象之间的紧耦合关系
装饰者模式
装饰者模式的定义:在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法。
- 通常运用在原有方法维持不变,在原有方法上再挂载其他方法来满足现有需求。
观察者模式
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。
- 观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
发布订阅模式
发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。
- 订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在。
发布订阅和观察者模式联系与区别
两种设计模式思路是一样的,举个生活例子:
- 观察者模式:某公司给自己员工发月饼发粽子,是由公司的行政部门发送的,这件事不适合交给第三方,原因是“公司”和“员工”是一个整体。
- 发布-订阅模式:某公司要给其他人发各种快递,因为“公司”和“其他人”是独立的,其唯一的桥梁是“快递”,所以这件事适合交给第三方快递公司解决。
- 上述过程中,如果公司自己去管理快递的配送,那公司就会变成一个快递公司,业务繁杂难以管理,影响公司自身的主营业务,因此使用何种模式需要考虑什么情况两者是需要耦合的。
区别
设计模式的理解与举例相关推荐
- Java查漏补缺(08)关键字:static、单例设计模式、理解main方法、类的成员之四:代码块、final关键字、抽象类、接口、内部类、枚举类、注解、包装类
Java查漏补缺(08)关键字:static.单例设计模式.理解main方法.类的成员之四:代码块.final关键字.抽象类.接口.内部类.枚举类.注解.包装类 本章专题与脉络 1. 关键字:stat ...
- [css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速?
[css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速? GPU: 图形处理器,用于处理图形有关的任务,用于渲染页面在css中使用 transform: translateZ(0),可 ...
- 设计模式(个人理解)
设计模式(个人理解) 工厂模式: 应用实例:一个工厂有一条流水线可以生产不同的产品,当客户需要某个产品时,直接告诉工厂产品名称.工厂就会用流水线生产对应的产品.客户不用关心产品时如何生产出来的,只需要 ...
- 23种设计模式通俗理解
23种设计模式通俗理解 1.根据目的来分 2.根据作用范围来分 3.GoF的23种设计模式的功能 1.FACTORY 工厂方法 2.BUILDER建造者模式 3.FACTORY METHOD抽象工厂 ...
- 基于计量学角度对传感器的灵敏度的理解和举例
基于计量学角度对传感器的灵敏度的理解和举例 灵敏度指标是考察传感器特性的主要指标之一,是对传感器设计.生产和选型过程中非常重要的参数.本文将基于计量学知识对灵敏度进行举例介绍. 一.灵敏度定义 灵敏度 ...
- 设计模式的理解:对23个设计模式的总结
设计模式名 ,链接可用 文档可下载:https://download.csdn.net/download/superSmart_Dong/16625368 设计模式 意图 适用的场景 关键实现过程 ...
- 设计模式的理解的总结
参考的博客:http://blog.csdn.net/wangeen/article/details/8272501 最近又把设计模式翻了一边,写个个人总结,这个总结比较简单,主要是一些理解,对于他们 ...
- 边缘独立(marginal independent)的理解及举例
1. 定义 ∀xi∈dom(X),yj∈dom(Y),yk∈dom(Y)\forall x_i\in dom(X), y_j\in dom(Y), y_k\in dom (Y),如果满足, P(X=x ...
- 条件独立的理解及举例
独立与条件独立 首先来看一个简单证明,A,BA,B 关于事件 CC 条件独立,证明,P(A|B,C)=P(A|C)P(A|B,C)=P(A|C) 证明: P(A|B,C)=====P(A|B,C)P( ...
最新文章
- 【多标签文本分类】Large Scale Multi-label Text Classification with Semantic Word Vectors
- 人脸识别经典算法一:特征脸方法(Eigenface)
- FPGA的设计艺术(15)逻辑设计及仿真利器之各式各样的循环
- 你们AI圈儿,已经引起了罗马教皇的警惕
- Silverlight+WCF 新手实例 象棋 WCF通讯跨域(十五)
- 蓝桥杯java第八届第一题--购物单
- python 画图_学python画图最快的方式——turtle小海龟画图
- 消息队列之RabbitMQ
- ES 在数据量很大的情况下如何提高查询效率
- php 操作 mysql 数据库常用方法集合
- 推荐一款Linux服务器连接工具FinalShell
- cmake指定输出安装目录
- Keyence激光打标机入门1
- shell 脚本教程 入门级
- 中科院阿里云联合发布11比特云接入超导量子计算服务
- BMS 中的安规设计
- 物联网应用层的关键技术有哪些
- 计算机网络拓扑结构的分析,计算机网络拓扑结构分析
- python判断火车票座位_利用Python实现命令行版的火车票查看器
- 乔本生涯, 为什么要这样做