观察者模式是一种非常流行的设计模式,也常被叫作订阅-发布模式。观察者模式在现代的软件开发中应用非常广泛,比如,商品系统、物流系统、监控系统、运营数据分析系统等。 现在我们常说的基于事件驱动的架构,其实也是观察者模式的一种最佳实践。当我们观察某一个对象时,对象传递出的每一个行为都被看成是一个事件,观察者通过处理每一个事件来完成自身的操作处理。 一、模式原理分析 观察者模式的原始定义是:定义对象之间的
状态模式的应用场景非常广泛,比如,线上购物订单、手机支付、音乐播放器、游戏、工作流引擎等场景。状态模式设计的初衷是应对同一个对象里不同状态变化时的不同行为的变化。那么,当我们遇见类似的场景时,该如何来使用状态模式呢?下面我们一起来看看吧 一、模式原理分析 状态模式的原始定义是:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了自己的类一样。 这个定义确实有点抽象,简单来说,状态模式就
策略模式在实际的开发中很常用,最常见的应用场景是利用它来替换过多的 if-else 嵌套的逻辑判断。除此之外,它还能结合工厂模式给客户端提供非常灵活的使用体验。下面,我们一起来看看吧! 一、模式原理分析 策略模式的原始定义是:定义一系列算法,封装每个算法,并使它们可以互换。策略让算法独立于使用它的客户端而变化。 在这个定义中,策略模式明确表示应当由客户端自己决定在什么样的情况下使用哪些具体的策略。
今天我们先来看一个原理看似很简单,但是理解起来有一定难度,使用场景相对较少的行为型模式:访问者模式。 一、模式原理分析 访问者模式的原始定义是:允许在运行时将一个或多个操作应用于一组对象,将操作与对象结构分离。 这个定义会比较抽象,但是我们依然能看出两个关键点:一个是运行时使用一组对象的一个或多个操作,比如,对不同类型的文件(.pdf、.xml、.properties)进行扫描;另一个是分离对象的
代理模式的原理非常简单,它和装饰模式很类似,都是在不改变同一个接口功能的前提下,对原有接口功能做扩展。但是代理模式的应用却比装饰模式更为广泛,因为代理模式并不执着于链式结构,而是采用更为灵活的单一结构,在很多框架和组件的设计里都能看到代理模式的身影,比如,JDK 的动态代理机制、Spring 的 AOP 机制、Dubbo 框架等。 那么,为什么代理模式能够获得如此广泛的应用呢?下面我们一起来看看。
享元模式的原理和实现都很简单,但是应用场景却相对狭窄,它和现在我们所熟知的缓存模式、池化模式有所联系,却又有不同。看完这篇文章后,相信你会找到这个不同之处。 一、模式原理分析 享元模式的原始定义是:摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,从而让我们能在有限的内存容量中载入更多对象。 从这个定义中你可以发现,享元模式要解决的核心问题就是节约内存空间,使用的办法是找出相
你是不是经常把门面模式和代理模式搞混淆?比如,业务 API 网关和 Nginx 网关是不是差不多?实际上这两种模式的本质原理是不同的。相信通过今天的文章,会帮助你找到一个更准确的答案。 一、模式原理分析 门面模式的原始定义是:为子系统中的一组接口提供统一的接口。它定义了一个更高级别的接口,使子系统更易于使用。 这个定义告诉我们门面模式的本质就是统一多个接口的功能。换句话说,当我们需要用更统一的标准
在前面几篇中,我们已经了解了结构型模式中的适配器模式、桥接模式和组合模式。本篇我们要介绍的装饰模式看上去和适配器模式、桥接模式很相似,都是使用组合方式来扩展原有类的,但其实本质上却相差甚远呢。 简单来说,适配器模式侧重于转换,而装饰模式侧重于动态扩展;桥接模式侧重于横向宽度的扩展,而装饰模式侧重于纵向深度的扩展。那么装饰模式到底有哪些需要我们重点学习的地方呢?下面,我们一起来看看吧 一、模式原理分
如果单纯从字面上来看,我们很容易将“组合模式”和“组合关系”搞混。组合模式最初只是用于解决树形结构的场景,更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一个统一功能。 虽然组合模式并不常用,但是学习它的原理能够帮助我们获得更多复杂结构上的思考。比如,MySQL 的索引设计中就是用了 B+ 树算法的组合模式设计,极大地提升了数据查询时的性能。组合模式的原理很容易理解,但
桥接模式的原理非常简单,但是使用起来会有一定的难度,所以相对于适配器模式来说,在理解桥接模式时,重点要能跳出局部,多从整体结构上去思考。 一、模式原理分析 桥接模式的定义是:将抽象部分与它的实现部分分离,使它们都可以独立地变化。 不过,这里的抽象常常容易被理解为抽象类,并将实现理解为继承后的“派生类”,但是这样理解存在局限性,因为 GoF 的本意是想表达“从对象与对象间的关系去看,做抽象实体与抽象
如果说创建型设计模式的关注重点在于一个对象内部结构的话(常常是接口与实现的组合),那么结构性设计模式的关注重点就在于多个对象之间的组合方式。 结构型设计模式一共包括七种:适配器模式、桥接模式、组合模式、装饰模式、门面模式、享元模式和代理模式。今天我们主要来聊聊最常用到的适配器模式。 一、模式原理分析 适配器模式的原始定义是:将类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工
原型模式最早出现于 1963 年的一个叫 Sketchpad 的系统中,说起 Sketchpad 你可能并不熟悉,但是说起 CAD(计算机辅助设计),现在在工程设计领域几乎无人不知,其实 Sketchpad 就被认为是现代 CAD 程序的鼻祖,主要思想是拥有一张可以实例化成许多副本的原图,如果用户更改了主工程图,则所有实例也会更改。这便是原型模式最初的思维模型。 不过在面向对象编程中,对象的原型在
今天我们接着来看另外一个工厂模式:工厂方法模式**(Factory Method Pattern)**。 工厂方法模式就是我们俗称的工厂模式,和抽象工厂模式很类似,但工厂方法模式因为只围绕着一类接口来进行对象的创建与使用,使用场景更简单和单一,在实际的项目中使用频率反而比抽象工厂模式更高。 一、模式原理分析 工厂方法模式的原始定义是:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。
在 GoF 的《设计模式》一书中,工厂模式被分为了三种:简单工厂、工厂方法和抽象工厂。(不过,在书中作者将简单工厂模式看作是工厂方法模式的一种特例。)在实际工作中,用得比较多的就是工厂方法模式和抽象工厂模式这两类。本篇文章,我们就先看一下抽象工场模式。 学习抽象工厂模式真正的重点和难点在于:如何找到正确的抽象。虽然抽象工厂模式很容易实现,但更重要的是我们要能意识到“正确的抽象往往都很简单也很底层”
事实上,建造者模式的代码实现非常简单,原理掌握起来也不难,而难点就在于什么时候采用它。比如,经常会遇到的以下两个问题: 为什么直接使用构造函数或者使用 set 方法来创建对象不方便? 为什么一定需要建造者模式来创建? 一、建造者模式分析 在 GoF 的书中,建造者模式的定义是这样的: 将复杂对象的构造与其表示分离,以便同一构造过程可以创建不同的表示。 接下来我们再来看建造者模式的通
一、设计模式的底层逻辑 关于设计模式,大家可能会说: 学习了很多设计模式的课程和文章,依然不会用设计模式; 设计模式适用场景没有设计原则多; 设计模式入门简单,精通很难; 设计模式太复杂看不懂; 面试前才会看设计模式; 设计模式不如面向搜索编程有用; ... 不可否认,一方面大家都很重视设计模式的学习,另一方面却又总是被设计模式搞晕,原因就在于没有真正明白设计模式最
无论是架构设计还是编码实现,现在都越来越离不开接口设计,接口可以说是新时代的“集装箱”,是得到了几乎所有人一致共识的通用标准。 GoF 在很多年前便建议大家应该针对接口编程,原因其实就是为了降低编程变化而导致风险出现的概率。 不过现实中,你可能遇见的更多是这样的情况: 定义好的 API 接口,却接收了额外的参数,导致程序异常退出; 查询返回的数据,没有回传预期的格式,数据处理出错; 一
关注点分离原则是一个帮助我们将复杂问题拆分成小问题的好方法。 什么是关注点?简单来说,在计算机科学中,关注点是能对程序代码产生影响的一组特定信息。比如,在面向对象编程中将关注点描述为对象,在面向函数编程中将关注点描述为函数,在架构设计中将模块、组件、框架描述为关注点,等等。 其实,在前面的文章里,我们也或多或少涉及了关注点分离原则的具体实践。比如,在分层架构中按照服务类型来划分层,层就被作为一个关
在软件开发中,你是不是经常因为沟通效率低下而烦恼? 所接手的维护项目代码质量低,频繁出问题,不得不一次又一次地找之前的人沟通; 团队中模块分散,各自编程风格不同,使用对方服务时需要反复沟通; 跨团队合作沟通,技术栈不同,需要反复沟通统一的标准。 你会发现,这些问题的本质其实都是因为代码而产生了学习成本和沟通成本,或者说,每一份代码都变成了需要重新学习的东西,自然需要反复研究和沟通。
在实际的研发工作中,你是不是遇见过以下场景? 一个平台系统,需要接入各种各样的业务系统,而这些业务系统都有自己的账号体系,平台需要兼容这些系统的账号体系,于是代码中出现了大量依赖于各种账号体系的代码。 一个网站页面,需要越来越多的频道(首页、搜索、分类等),不同频道对应的个性化需求各不相同,并且各种页面的标准组件、布局、模板,以及与后端交互框架也各不相同,不同体系的代码依赖非常紧密。
说到面向对象编程,有一个原则几乎每个程序员都知道,那就是 SOLID 原则。关于它的资料介绍也非常丰富,实践例子也很多。但实际上你很可能把 SOLID 原则都用错了,并且还无意识地一直在滥用它。 之所以这么说,一方面是因为很多时候你都将每一个原则分开使用,容易造成过度解读。比如,在使用接口隔离原则时容易只关心接口,而忽略不同实现,或者不关心接口之间的关系以及和整体系统之间的关系。另一方面是因为它总
在面向对象编程中,你是不是经常听到“要实现代码间的职责分离”,但是具体什么样的代码才算得上是清晰的职责分离,似乎却又总是模糊不清。比如: 代码模块越多职责越清晰? 按照需求来分配职责就是职责分离? 模块化就是职责分离? 实际上,要想写出“职责分离”的代码,单从字面含义是很难下手的,因为业界并没有统一的通用标准。比如,什么是职责分离?为什么职责分离很重要?具体如何实现职责分离? 所以
维护代码是程序员非常重要的日常工作之一,那么你是否曾遇见过以下问题? 接手维护项目,却发现文档缺失、代码无注释,加上维护人离职,基本只能靠猜来梳理代码逻辑。 代码风格过于抽象(命名过短、魔鬼数字、重名方法等),看不懂,也不敢轻易修改。 运行代码出现故障时,不打日志,不抛异常,导致定位问题需要耗费很长时间。 大段的if-else代码嵌套组合,调用逻辑复杂冗长,扩展性差,重构优化费时、
在实际的软件开发中,我们经常会写下面这样的代码: final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath(); 代码看上去没有太大的问题,但实际上其中任意一个方法发生变化时,这段代码都需要修改。因为调用是依赖的每一个细节,不仅增加了耦合,也使代码结构僵化。 迪米特法则正是为了避免对象间出现这样过多的细节
大家发现没,设计原则通常都有一个很普遍的特点:语言很简练,听上去很有道理,但是拿来指导实践根本无从下手。比如说,在学习简单原则(也就是我们平时说的 KISS 原则) 时,你可能遇到过下列问题: 为什么身边的程序员都告诉你保持“简单”代码很重要? 什么才是好的“简单”代码? 如何能写出“简单”的代码? YAGNI 原则和 KISS 原则是相同的吗? 这些问题看上去简单,回答起来却
在软件开发中,我们都学习过一些经典的设计原则,其中包括面向对象原则(SOLID)、简单原则(KISS)、单一原则(DRY)、最少原则(LoD)、分离原则(SoC)等。 分开来看这些原则时,会觉得它们都很有道理,似乎只要照着用就能提升编程能力和代码质量,但为什么到真正编码时却会有选择困难的矛盾感觉呢? 其实原因就在于,有的原则之间是相互冲突的,而有的原则之间又是彼此重复的。 虽然设计原则是用来指导编
在工作中,大家是否曾遇到过下列情形? 团队辛辛苦苦做出的软件产品,却被客户云淡风轻地评价一句:“这不是我想要的。” 在新的项目中,自己作为系统的主要设计者采用了很多新技术,却发现团队成员的技术水平参差不齐,项目进度不断延期。 每次一到季度或年度总结的时候,自己明明做了很多项目,付出了很多努力,但是被问到这些项目具体取得了哪些收益、对业务有哪些提升时,却顿时语塞。 要解决这些问题,不
Unix 操作系统诞生于 20 世纪 60 年代,经过几十年的发展,技术日臻成熟。在这个过程中,Unix 独特的设计哲学和美学也深深地吸引了一大批技术开发人员,他们在维护和使用 Unix 的同时,Unix 也影响了他们的思考方式和看待世界的角度。 什么是 Unix 哲学?简单来说,Unix 哲学是一套基于 Unix 操作系统顶级开发者们的经验所提出的软件开发的准则和理念。 也就是说,Unix 哲学
在工作中,大家可能常常会发现,很多人将 Java 设计模式、大学里学的高等数学和编译原理等,视为脱离实际工作的知识。 但不管是面试还是实际工作中,是不是经常听到大牛前辈们给“洗脑”,说设计模式很重要?为此可能还专门买书或参加培训学习过,可往往都因为应用效果不佳,从开始的很重视,到后来慢慢地习惯性忽略,最后在你心中它的重要程度可能还远不如明天要交差的需求。 工作多年后,回过头再来看,其实,当时这些困
一、解决真实问题很重要 先给你讲个故事。多年前刚参加工作时,刚转正不久就被派到客户现场解决一个紧急问题,对于一个刚入职场的新人小白来说,内心其实是非常惊慌无措的。 刚开始还算顺利,前辈同事们已经大致定位到了问题原因,也做了一些补救措施,貌似已经没有问题了。但不久后的一天凌晨,在同步数据的过程中,系统突然就失灵了,重启之后,问题仍然出现。此时,部分数据丢失,而且客户开始越来越没有耐心。 而后,另一位
Copyright © 2005-2024 51CTO.COM 版权所有 京ICP证060544号