设计模式

2016-09-02  本文已影响84人  潘逸飞

工作了也1年多了,最近2个月把那本经典的设计模式看了一遍。还是蛮有收获的。至少比以前在学校的时候看多了很多的体会。希望接下来的工作中,能够慢慢地成为自己的利器之一。这里简单的记录一下自己的读书笔记。

抽象工厂模式--对象创建型模式

意图:提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类。产品种类是固定的,产品系列可以被替换~想增加产品种类会比较麻烦,因为所有工厂都必须改。

就是定义了一个抽象类,这个类定义了一些接口,然后每种想创建的都是具体的子类来实现具体的功能,然后用户们完全根据抽象类提供的接口来使用。客户完全不知道他们使用的是哪些具体类。

适用性:

优缺点:

我们使用工厂的时候,可以通过传递一个参数来指示要创建的对象的种类的参数。

BUILDER(生成器)--对象创建型模式

意图:将一个复杂对象的构建和他的表示分离,使同样的构建过程可以创建不同的表示。不变的是构建步骤,构建的具体操作可以被多种替换~

就是用户使用一个director来根据一定的步骤来调用builder的创建方法,然后用户从builder那里得到最后生成的东西。(之所以不从director拿是因为director里面不知道生产的是什么产品,只有builder和用户才知道产品是什么)

适用性:

效果:

这里说抽象工厂和建造者模式的区别是:builder是一步步构造复杂对象,抽象工厂着重于多个系列的产品对象,抽象工厂直接拿到产品,builder最后拿到。

工厂方法--对象创建型模式

意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到他的子类。选择使用哪个工厂的事情交给了使用者。每一个新的产品都得新增一个工厂。

适用性:

效果:

书里没有介绍简单工厂,就是只有一个创建的工厂,通过传入的参数的不同来创造出不同的产品,坏处是要增加新产品的时候得修改原有的工厂,违反了开放封闭原则。

PROTOTYPE(原型) --对象创建型模式

意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

效果:

缺点:每个类都得实现一个clone借口

这个模式主要是GUI时代的产物,那个时候需要的就会复制一个东西,而现在这种需求很少了。前端就更少了,前端没有类的概念,复制一个对象的成本很小。

SINGLETON(单件) --对象创建型模式

意图:保证一个类只有一个实例,并且提供一个访问它的全局访问点

适用性:当类只能有一个实例并且客户可以从一个众所周知的访问点访问它的时候,类负责保存唯一实例,并且通过截取住创造函数的方式来截取住

效果:

ADAPTER(适配器) --类对象结构性模式

适用性:

目的是改变已经存在的接口

结构的话:

效果:

BRIDGE(桥接) --对象结构型模式

意图:将抽象部分与实现部分分离,使得他们都可以独立的变化

适用性:

结构:

就是抽象类内部聚合了一个具体实现类的抽象,然后在内部接口调用这个具体实现类接口的实现。然后创建的时候只要set一下内部的具体实现类就好了。想切换的时候就重新set就好了。

效果:

COMPOSITE(组合) --对象结构型模式

意图:使得用户对于单个对象和组合对象的使用具有一致性

适用性:

结构:

就是定义一个类,既有普通的图元所拥有的操作方法,又有作为容器的那些添加,删除,获得子孙的方法,。然后叶类继承这个类,实现基本操作,容器类继承,在内部聚合叶类。

效果:

DECORATOR(装饰) --对象结构型模式

意图:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更加灵活

适用性:

结构:

就是一个装饰器类,聚合真实的组件,提供与真实组件一样的接口,然后在自己的接口中调用真实组件的接口。多种装饰器的话就都继承

效果:

相关模式:

适配器模式不同之处在于他会给对象一个新的接口

FACADE(外观) --对象结构模式

意图:为子系统的一组接口提供一个一致的界面,定义了一个高层接口,接口使得子系统更容易使用。

适用性:

效果:

facade也有点像适配器,但是facede是创造了新的接口,而适配器是使两个已有的接口协同工作

FLYWEIGHT(享元) --对象结构型

意图:运用共享技术有效支持大量细粒度的对象

注意:这里很大程度上并不是取决于创造的代价,而是调用的频率

适用性:

结构:

就是有个享元抽象类,然后有个存储着享元的池子。普通情况下都是直接从池子里获取享元,当不需要共享的时候。也有一个子类实现了享元接口,可以直接new出来,大部分时候都是从池子里面拿。注意享元内部的状态都是共享的状态。想要不同的地方,只能使用享元的时候从外部传入。

效果:

共享的flyweight越多,空间的节省也就越大。

PROXY(代理) --对象结构型模式

意图:对其他对象提供一种代理以控制这个对象的访问。

使用性:

实现:

就是代理类里面聚合了一个实例,然后提供了与实例一样的接口,将操作代理到实例上。

效果:

其他模式:

CHAIN OF RESPONSIBILITY(职责链) --对象行为型模式

意图:就是一个行为沿着一个对象链冒泡,可能会被其中的某个对象处理,使得多个对象都有机会处理对象,避免了发送者和处理者之间的耦合关系。

适用性:

结构:就是很多个处理者,他们都拥有处理请求的方法并且可以访问到他们的上一级,一个请求从底层向上传递,可能会被其中的一个处理了或者继续向上传递。

效果:

总结:如果这个链经常被修改的话,是可以弄成这个模式的,不一定那种if else的就一定合适,主要还是看项目的演化方向

COMMAND(命令) --对象行为型模式

意图:将一个请求封装成一个对象,可以使用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作

适用性:

结构:就是客户端声明一些实现的命令对象,并且给他指定好接受者对象。然后发起者拥有这些命令对象。真正的触发由发起者来发起。发起者可以对拥有的这些个命令进行各种排序啊,状态的存储啊等等操作。

总结:就是将一个命令的直接执行过程拆开,分成了发起者和执行者两个角色。然后用一个命令对象来管理他们的关系。通过这个命令对象我们可以存储一些状态,通过这些个状态,我们可以一个是松耦合,一个是支持排队,取消,以及修改以及日志。

效果:

INTERPRETER(解释器) --类行为型模式

意图:给定一个语言,定义它的文法的表示,并定义一个解释器。解释器使用该表示来解释句子。

适用性:

结构:其实主要是在context里面有解析整个语句的过程,会使用一个栈,这个栈里会一步步的解析,最后的结果是各个解释的类的结果(其实就是生成一个抽象语法树)。最后的结果是一个嵌套了很多解释器的结果。栈其实就只有一个内容。每个解释类实现不同,但是都有同一个方法,基本会有两种解释器,一种就是值,一种就是操作。

效果:

总结:使用的情况还真的很少,毕竟很少人会来写一个语法。最后就是通过遍历来生成一个抽象的语法树。

ITERATOR(迭代器) --对象行为型模式

意图: 提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露内部表示。

适用性:

结构:这个集合对象也是一个抽象的接口,也会有一个实现的集合对象。然后申明了一个抽象的迭代器,然后一个具体实现的迭代器(new的时候会传入一个具体的集合对象,这里切换迭代器其实是一种工厂模式)。两个抽象主要是为了遍历不同的结构和不同的遍历方法。

效果:

MEDIATOR(中介者) --对象行为型模式

意图:用一个中介对象来封装一系列的对象交互,使得各对象不需要显示的相互引用。从而松散耦合。而且可以独立的改变他们之间的交互。

适用性:

结构:就是定义了一个同事的抽象,然后每个实现的子类的实例拥有中介者的引用。每个指令发出去都是通过中介者来发。中介者拥有着这些个实例的所有的引用。他会针对发出的请求的实例做不同的事情。

效果:

MEMENTO(备忘录) --对象行为型模式

意图:不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态以便恢复。

适用性:

结构:就是发起者负责根据自身状态创建备忘录对象(他可以通过备忘录来进行自身的恢复工作)。然后外部还有个负责人来保存这个备忘录的引用,提供get,set方法。发起者再从这个负责人这里拿取来恢复。

效果:

OBSERVER(观察者) --对象行为型模式

意图:定义对象之间的一对多的依赖关系,当一个对象状态发生改变的时候,依赖的对象得到通知并自动更新

适用性:

结构:就是一个抽象对象类,里面有添加和删除观察者的方法,还有通知的方法。具体的对象实现这个类,然后保存有自己内部的状态。有个观察者的抽象,里面只提供了update方法,然后具体的观察者实现抽象类并存有内部的状态。

效果:

总结:其实我们js中大部分的观察者都是推模式,但是真正的观察者其实是拉模式。

STATE(状态) --对象行为型模式

意图:允许一个对象在他的内部状态改变时改变他的行为。

适用性:

结构:就是一个context内部聚合了一个state的实例。state定义了context的特定的状态的行为。注意每个实现了state的类都要把这些个行为实现。然后通过切换状态然后重新调用方法来实现。

效果:

总结:这个模式其实和职责链有些相似,当初我也觉得职责链能够解决多个if的场景,后来发现状态模式更适合。因为状态是单个对象的状态的切换,而职责链是多个对象之间的切换。而且职责链其实是switch。而状态是if else。这个模式和享元可以配合。因为他的state是独立的。注意状态这个概念是持久化的,才能叫状态。必须是严格的显示依赖于状态才行。

STRATEGY(策略) --对象行为型模式

意图:定义一系列的算法,把他们一个个封装起来,使得他们可以相互替换。使得算法可独立于使用它的客户而变化。

适用性:

结构:很简单,就是一个上下文聚合了一个抽象的算法。这个算法会有很多种实现。

效果:

总结:这个玩意和桥接模式很像,但是区别还是有的,首先策略是行为模式,而桥接是结构性模式。桥接的的调用方是可以有自己的变化的,而策略模式不能有自己的变化。桥接模式更多的是体系的隔离。可以说桥接模式包含着策略模式。但是桥接模式比策略更加的高级一些。更多的是一种接口隔离的原则,使之可以松散的耦合。主要是看一个问题的角度问题

TEMPLATE METHOD(模板方法) --类行为型模式

意图:定义一个操作算法的骨架,将一些步骤延迟到子类。是的不改变算法的结构就可以重新定义特定步骤

适用性:

结构:就是声明一个模板类,大部分的结构都是已经实现好了的,一些特定的步骤用虚方法来写,然后子类其实只要实现虚方法就好了

效果:

总结:其实模板方法的运用就是提供了钩子函数,在定义了具体的执行顺序(也就是模板)的时候,对外提供了在特定的点执行的能力的钩子函数。

VISITOR(访问者) --对象行为型模式

意图:表示一个作用于对象结构的个元素的操作。使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

适用性:

结构:就是一个对象结构内部有多个对象。访问内部的这些对象的时候。传入一个访问者对象。然后调用特定的方法的时候,把自身传进去。然后在访问者对象里面根据传入的是谁来决定相应的操作

效果:

总结

个人感觉设计模式其实首先得有后续的代码的变化。其次要有一定的复杂度。一般都是将变化隔离开。或者将复杂的地方,包括算法(策略模式),多个对象之间的联系(中介者模式)等等进行一定的隔离。

文章可以直接访问我的前端网站来查看,平时的日常整理也都会记录上去。

上一篇下一篇

猜你喜欢

热点阅读