Keep Thinking Keep Moving

设计模式 标签

访问者模式(Visitor)

定义:

将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。

通俗解释:

访问者模式的确挺不好理解的。我们举一个非常简单的例子,例如年底服装公司要盘点库存了。仓库衣服也有裤子,小A负责盘点衣服,小B负责盘点裤子。如果将这两个盘点都写在仓库类当中的话,一旦新品类(比如鞋子)出现的话,又需要在仓库类中修改代码了,所以为了遵守开闭原则,我们将员工盘点货品的方式抽离出来,进行解耦。小A和小B其实就是访问者。而裤子和衣服就是元素。仓库类是某种数据结构。

2019-09-03 0 评论 298 浏览
阅读全文

模板方法模式(Template Method)

定义:

定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

通俗解释:

好比相亲一样,媒人跟男方说,你们约会的流程就是先逛街,再吃饭,再看电影,然后就结束约会啦。具体怎么逛街,吃什么饭,看什么电影,男方自己决定。模板方法模式就是这么的简单。

2019-09-02 0 评论 325 浏览
阅读全文

策略模式(Strategy)

定义:

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

通俗解释:

玩过英雄联盟的小伙伴都知道有野兽之灵乌迪尔这个英雄,这个英雄拥有不同的形态,例如熊形态,龟形态,老虎形态。如果代码编写成if-else,通过判断野兽之灵是什么形态来进行什么样的攻击的话,后期游戏想继续增加新的形态的话,就会破坏原有的代码。所以我们必须遵循开闭原则,通过将形态抽离出来进行解耦。在JDK当中的集合排序,通过传入不同的比较器来进行比较,也是策略模式的体现。

2019-09-02 0 评论 323 浏览
阅读全文

状态模式(State)

定义:

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

通俗解释:

玩过英雄联盟的同学都知道卡牌大师这个英雄。卡牌大师有一个技能是根据卡牌的颜色攻击对手的话,会有不同的效果。这种效果体现在攻击力,耗蓝量,还有特殊效果。并且出牌颜色是随机的,所以这边就有状态的流转。如果我们采用if-else方法的话,就需要在攻击方法,耗蓝量,以及特殊效果上依次用if-else判断当前的牌的颜色来写代码。但这就违反了开闭原则。我们应该将这些“业务逻辑”抽取出来,放进一个一个的状态类当中。状态模式和策略模式很相像,状态模式主要不同在于对象内部状态的流转,并且行为是随着状态自动改变的。而策略模式是通过动态的切换策略来更改当前类的行为。

2019-09-02 0 评论 360 浏览
阅读全文

观察者模式(Observer)

定义:

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

通俗解释:

好比一个网络聊天室模型。有多个聊天者在聊天室内聊天,其中一个聊天者发送一条消息,则需要通知所有聊天者查看消息。例如我们App当中的通知机制也是如此,保存用户的标志,然后挨个给每个用户推送信息。

2019-09-02 0 评论 300 浏览
阅读全文

备忘录模式(Memento)

定义:

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。

通俗解释:

我们玩角色扮演单机游戏的时候都需要进行存档。如果角色不小心死亡或者任务失败的时候我们就可以从之前存储的多个存档进行恢复。我们在IDEA编写代码的时候,发现修改错了,也可以用Ctrl+Z进行撤销修改,恢复到一开始的代码。

2019-09-01 0 评论 354 浏览
阅读全文

中介者模式(Mediator)

定义:

定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

通俗解释:

网游中玩家进行装备买卖的话,都需要满世界喊话。比如求购XX装备,或者卖XX装备要的私聊这样。买家与卖家就变成了紧密耦合,所幸的是现在很多网游当中都有交易市场功能。这个交易市场就相当于一个中介者。买家和卖家不再直接联系,而是通过交易市场进行交易。在软件开发中有很多这种例子,比如MVC 框架中,控制器(Controller)就是模型(Model)和视图(View)的中介者。早期的JSP开发中,Model和View就是直接耦合在一起,在维护上面变得十分困难。这里的Model和View就像买家和卖家一样。有一句玩笑话就是在软件开发中没有增加一层抽象解决不了的问题。

2019-09-01 0 评论 282 浏览
阅读全文

迭代器模式(Iterator)

定义:

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种对象行为型模式

通俗解释:

在开发当中,我们经常需要访问一个聚合对象中的各个元素,如遍历List,通常的做法是将链表的创建和遍历都放在同一个类中,但这种方式不利于程序的扩展,如果要更换遍历方法就必须修改程序源代码,这违背了 “开闭原则”。
如果聚合类中不提供遍历方法,而让用户自己实现呢?这也会暴露了聚合类的内部表示,使其数据不安全;增加了客户的负担。迭代器模式能较好地解决以上问题,它在客户访问类与聚合类之间插入一个迭代器,这分离了聚合对象与其遍历行为,对客户也隐藏了其内部细节,且满足“单一职责原则”和开闭原则,如 Java 中的 Collection、List、Set、Map 等都包含了迭代器。

2019-09-01 0 评论 292 浏览
阅读全文

解释器模式(Interpreter)

定义:

给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。

通俗解释:

我们可以用一个最最简单的计算器程序来举例,该计算器只有加法和减法并且不能加括号。我们通过输入一串简单的表达式例如:1+3+4-5然后根据计算得出结果为3。这其中的每个数值和符号都属于一个表达式。每种表达式都对应一种功能,可以是保存数值的功能,也可以是计算数值的功能。解释器模式其实我们在实际业务开发中比较少碰到,例如渲染页面的标签语言或者Spring EL 表达式也属于也属于解释器模式。总得来说,解释器相当于一个傻瓜版的编译器。

2019-09-01 0 评论 267 浏览
阅读全文

命令模式(Command)

定义:

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

通俗解释:

假设司机是命令发出方,而车子是命令接收方。司机与车子通过命令对象来传达指令操作车子从而进行解耦。司机并不知道最终命令执行的是谁,车子也不知道是谁在下达命令。

2019-08-31 0 评论 307 浏览
阅读全文

责任链模式(Chain of Responsibility)

定义:

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

通俗解释:

这个模式非常简单。就好比小明在公司请假。先把假条给组长审批,组长再把假条给经理审批,经理再把假条给老板审批。

2019-08-30 0 评论 241 浏览
阅读全文

代理模式(Proxy)

定义:

由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

通俗解释:

好比去动车站买动车票,如果家离动车站比较远的话肯定就非常不方便。这时候我们就可以选择离家近的动车站代售点买票。这里的代售点就相当于代理类。代售点出票也是先从动车站出,然后再售卖给我们。比如Spring中的AOP原理也是代理模式,通过一个代理对象访问真实的对象。例如Hibernate的延迟加载也是,load方法查询得到的对象仅仅只是一个代理对象,等到真正想要获取对象属性的时候才进行数据库查询。

2019-08-30 0 评论 294 浏览
阅读全文

享元模式(Flyweight)

定义:

运用共享技术来有効地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。

通俗解释:

设计一个围棋游戏程序,每下一个棋子我们就新建一个棋子的对象。棋盘大小的是19*19=361的位置,下满棋盘的话就需要创建361个对象。而分析一下,其实棋子在表现模型上是一样的,只分为黑棋和白棋。我们只需要共享一个黑棋一个白棋,在下棋的时候通过传入棋盘的坐标即可。例如JDK当中的String类型,不同地方相同的字符串会引用缓存池当中的同一个字符串,这也是享元模式的一种体现。

2019-08-30 0 评论 325 浏览
阅读全文

门面模式(Facade)

定义:

是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

通俗解释:

玩单反的人都知道要出拍一张好的照片,涉及到调光圈,快门,调焦距,ISO等复杂的拍摄技巧。那普通人想拍照又不想学这些复杂的拍摄技巧呢?不用担心,因为有傻瓜相机,只需要按一下快门即可拍出一张照片。傻瓜相机就相当于一个门面,而那些光圈,快门,焦距属于复杂的子系统。我们就通过门面,屏蔽了子系统的复杂性。

2019-08-30 0 评论 257 浏览
阅读全文

组合模式(Composite)

定义:

有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。

通俗解释:

假设我们需要做一个计算零件价钱的类。输入一个零件就计算出对应的价钱。那如果我们有一个成品它由3个大零件组成,每个大零件又由3个小零件组成。这个成品一共包含了9个零件。这时候我们就需要一个接收单个零件的计算方法,还有一个接收成品的计算方法。如果这样的话,就得需要重载两个方法,并且还需要让用户自己判断这个物品是成品还是零件。所以这时候就需要使用组合模式,将零件和成品统一的看待,类也仅需一个计算方法,它可以接收零件和成品的共同抽象类。

2019-08-29 0 评论 263 浏览
阅读全文

装饰者模式(Decorator)

定义:

指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

通俗解释:

在很多网络游戏当中,武器都可以进行附魔。比如一把普通的刀。可以附魔火属性,也可以再附魔冰属性,还可以再附魔风属性。对于武器的附魔。相当于动态地给武器添加额外的功能。在装饰者模式中,被装饰的对象和装饰对象继承的是同一个接口,所以对象被装饰过后还是跟原来的对象接口一致,所以就可以不同组合的进行装饰。

2019-08-29 0 评论 336 浏览
阅读全文

桥接模式(Bridge)

定义:

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

通俗解释:

假设我们写一个画图程序,要实现画长方形、正方形、圆形。很简单我们只需要抽象出一个Shape抽象类,然后长方形、正方形、圆形继承这个Shape类,绘制方法就交给子类实现。但是如果再加上一个需求,要绘制红黄蓝三种颜色的图形怎么办?如果再用继承来实现这个需求的话,光长方形就需要红长方形,黄长方形,蓝长方形三个子类。依次类推,一共需要继承出九个子类。SOLID原则讲到要尽量用聚合来替代继承来扩展功能。多层级的继承代码耦合性非常大,而且类不利于重用。这时候就需要桥接模式。通过抽象的Shape类当中去持有抽象的Color类,打破原本的继承关系,那么Shape类的扩展和Color的扩展都可以独立的变化不需要修改原类,这也是开闭原则的一种体现。

2019-08-29 0 评论 247 浏览
阅读全文

适配器模式(Adapter)

定义:

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

通俗解释:

有一个中国人和一个日本人,他们都只会母语并且不想再学习其他语言(意味着不修改两个不兼容的类的代码)。但是他们之间又想进行交流,那怎么办呢?这时候如果有翻译的话就可以让中国人和日本人不用学习新的语言,即可互相交流。这里的中国人和日本人是互不兼容的两个接口,而翻译就是他们之间的适配器。

2019-08-28 0 评论 402 浏览
阅读全文

单例模式(Singleton)

定义:

该模式只涉及到一个类,该类负责创建自己的对象,同时确保只有唯一一个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

通俗解释:

好比以前的计划生育一对夫妻只能有一个孩子,因为生育抚养孩子的成本太高了。所以限制只能有一个。单例模式也是如此,为了节省创建对象的成本或节省对象占用的内存空间而实现的模式。

单例模式最重要的三点特征如下:

  • 单例类只有一个实例对象;
  • 该单例对象必须由单例类自行创建;
  • 单例类对外提供一个访问该单例的全局访问点;

2019-08-28 0 评论 296 浏览
阅读全文

原型模式(Prototype)

定义:

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

通俗解释:

美术课上老师布置了一个素描作业。然后同学们让美术课代表画了素描作业。其他同学就可以拿着这份素描作业去复印店复印。其他同学完全不用知道怎么画这个素描。美术课代表画的素描作业就是已经创建实例。它作为原型。用这个原型复制出新素描的话,无需关心素描细节。

2019-08-28 0 评论 368 浏览
阅读全文