设计模式(Design pattern)在软件行业一直都扮演着很重要的角色。最近感受本身对设计模式的知识有些遗忘了,虽然之前也看了不少,可是坦白说,其实并无怎么理解。基本仍是为了应付面试。而后,在工做当中,也不多用到那么多的设计模式,大部分工做都是涉及单例模式,工厂模式或者装饰模式。慢慢地,就以为设计模式好像离本身愈来愈远了,变成了一种似懂非懂的东西。因而乎就赶忙脑补一下。脑补的时候,感受知识确实是一种温故而知新的东西。java
其实,设计模式更可能是表明着一种思想,就像面向对象同样。你在开发的过程当中,也学已经用了不少种设计模式,只是你不知道原来这就是设计模式中某一种…也由于这样,若是你把设计模式看成一种思想思惟而不是一种工具去看待的话,那么理解起来也会舒服和容易不少。因为设计模式基本面向的是OOP的语言,因此OOP的思想应该是你阅读的基础。android
这里想顺便插播几句关于教育的问题。咱们一直以来都批判咱们国家的教育太过死板,总是填鸭式的教学。我我的认为,这些真的不能算做什么很劣质,而后外国那套很优良。咱们如今回想起来,会发现,这种咱们称之为填鸭式教学,其实也有它好的一面,那就是不管怎么样,你老是有必定理论知识的基础。至于日后的我的发展、学习以及工做的种种影响,并不能怪罪于这种教学方式,而是咱们赋予了教育太多的使命和任务才让本来单纯传播知识的这项任务变得如此沉重不堪……之因此,插播这个,也是但愿同窗们不要去抱怨过去的鸭子,过去的鸭子再难吃也过去了,好好去捕捉其余鸟兽吧~面试
这篇关于设计模式主要仍是偏向概况,而且主要是关于基本的那23种模式,不会去讨论如MVC、MVP或其余MV*等衍生的设计模式。若是你对好多基本的概念不了解仍是先去看看一些详细的书籍,这样会比较好一些。好了,全部的废话和水分都说加完了,下面开始进入干货模式。算法
基础设计模式分为三种类型,共23种。设计模式
建立型模式:工厂方法模式、抽象工厂模式、建立者模式、原型模式、单例模式。数组
结构型模式:外观模式、适配器模式、代理模式、装饰模式、桥接模式、组合模式、享元模式。数据结构
行为型模式:模版方法模式、观察者模式、状态模式、策略模式、职责链模式、命令模式、访问者模式、调停者模式、备忘录模式、迭代器模式、解释器模式。并发
1、建立型模式 —— 该类模式研究的是若是更好地建立一个对象的问题框架
1,工厂方法模式(Factory Pattern) —— 设计一个专门的工厂类Factory,用来专职建立一些比较复杂的对象(就是它的初始化比较复杂,不是单纯new Constructor()那么简单)如:Bitmap bitmap = BitmapFactory.createBitmap(a,b,c);工具
2,抽象工厂模式(Abstract Factory Pattern) —— 该模式是基于 工厂方法模式 。设计一个抽象的工厂接口,而后再实现它产生具体的工厂类来建立那些比较复杂的对象。当咱们须要工厂方法类解决复杂对象的建立问题并发现复杂对象属于一系列相关联的对象时,也即出现了对象建立的管理问题时,就能够考虑抽象工厂方法类了。
三、建立者模式(Builder Pattern)—— 当咱们须要建立一个复杂的对象,而且这个复杂的对象在使用以前的组装也比较复杂的时候,形如Android的AlertDialog。那么就能够考虑使用建立者模式了。
四、原型模式(Prototype Pattern)—— 当咱们须要动态建立或加载具备必定层次的对象,这些对象对外都是相对稳定的时候,原型模式就比较适合了。由于原型模式实现的基础就是java的clone,也就是复制一个对象,而后直接操做已复制的对象。
五、单例模式(Singleton Pattern)—— 该模式应该是用得比较多的模式。由于咱们常常碰到一些场景就是,只能容许有一个实例的状况。最多的就是打印日志了。可是咱们常常会发现一些其实原本是一种Util类型的类,却写成了单例,这是彻底没有必要的。
2、结构型模式 —— 建立型模式解决了关于对象建立的问题。可是对象建立后使用的过程当中,就会碰到不少对象组成以及对象与对象之间的关系管理问题。而这类问题就是结构型模式所要去解决的。
一、外观模式(Facade Pattern)—— 为子系统中的一组接口提供一个一致的界面,定义一个高层接口。该模式实现了系统之间的松耦合关系,也使得这一子系统对外的接口更加简洁和容易使用。
二、适配器模式(Adapter Pattern)—— 一个接口所产生的结果老是固定的,可是对外则老是有各类各样的结果需求。如何让一个返回单一结果类型的接口,可以知足各类调用需求(固然这个需求也是创建在该接口的原始返回数据上的),这就是适配器模式所要处理的场景,该模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。
三、代理模式(Proxy Pattern)—— 该模式是为了强化一些核心类的功能。在调用目标对象的方法以前以后均可以执行特定的操做。因此,要实现代理模式,通常至少有一个abstract或interface,一个RealObject和一个ProxyRealObject,同时ProxyRealObject附带着RealObject的应用,当外部调用接口方法时,代理类会在调用真正核心类以前以后作一项操做。
四、装饰模式(Decorator Pattern)—— 在没必要改变原类文件和使用继承的状况下,动态地扩展一个对象的功能。经过建立一个包装对象来包裹真实的对象,添加一些额外的职责。乍一看,其实挺像代理模式的。由于代理模式也能够实现这样的功能。可是你们要注意代理模式是要实现接口的。而装饰模式更多的是为了处理那些不适合经过生成子类来实现的,好比有大量独立的扩展,若是为支持每一种组合将产生大量的子类,那将会使得子类数目呈爆炸性增加。固然还有一种状况也多是由于类的定义被隐藏,或者它是个final类不能用于生成子类。
五、桥模式(Bridge)—— 有些类型因为自身的逻辑,它可能具备多个维度的变化,如何应对这种“多维度的变化”就是桥模式所要解决的问题。好比类型A有A1,A2,A3,类型B也有B1,B2,B3,而实际使用的类型则是A*B*,也就是说若是按传统继承的方法则会有3*3=9种独立的类型。任何一个维度再加1或者再增长一个维度的变化,那么最终类型的数量就会成倍地增长并且若是后期稍有改动,维护将很是繁琐,显然就不太合理。咱们试试用桥模式去分析这个问题,咱们就会发现最终类型有两个维度的变化,A*和B*的变化是独立的也是肯定的,无法改变,可是对外提供的是A*B*倒是变化多端的。咱们应该给A和B创建一座桥,使得A和B独立变化,自由组合。这也就是桥模式形象的解释。
桥接模式将继承关系转换为关联关系,从而下降了类与类之间的耦合,减小了代码编写量。可是在它的定义描述的是:“将抽象部分与实现部分分离,使它们均可以独立的变化。”这里要注意如下抽象部分并非指的是java里面的单纯的interface而是形如A与B同样的抽象化的类型,这里包括接口A和B,同时也包括A* 和B*;实现部分指的是最终给外部使用的部分,即A*B*组合。
六、组合模式(Composite Pattern)—— 又称部分-总体模式,组合模式使得用户对单个对象和组合对象的使用具备一致性的操做。经典形象例子就是树形结构的文件系统。在让外部系统使用的时候,可让他们统一对待目录与文件,进行删除增长。
七、享元模式(Flyweight Pattern)—— 该模式通俗的讲就是复用咱们内存中已存在的对象,下降系统建立对象实例的性能消耗。更广义一点就是,运用共享技术有效的支持大量细粒度的对象。若是一个应用程序使用了大量相近甚至重复的对象,而这些对象形成了很大的存储开销的时候就能够考虑是否可使用享元模式。
3、行为型模式 —— 对象的建立和结构都处理好了之后,新的问题又来了,就是对象的行为要怎么样才更加合理,更加有效率,更加协调地与各个组件完成一系列的任务。行为模式就是专门研究这些问题。由于行为的多样性,也致使了行为型模式有不少种方案。要理解背后的思想,才能灵活运用。
一、模板方法模式(Template Pattern)—— 就是定义一种模板逻辑来处理相似逻辑框架问题的设计模式。在面向对象开发过程当中,咱们会遇到这样的一个问题:咱们知道一个算法所需的关键步骤,并肯定了这些步骤的执行顺序。可是某些步骤的具体实现是未知的,或者说某些步骤的实现与具体的环境相关。好比定义一个操做顺序的抽象类,其中有个final方法RunAll会依次调用run1,run2,run3,而后子类就能够不改变一个算法的结构便可重定义该算法的某些特定步骤。该模式的核心:封装不变部分,扩展可变部分;行为由父类控制,子类实现;提供公共部分代码,便于维护。
二、观察者模式(Observer Pattern)—— 目标对象管理全部相依于它的观察者对象,而且在它自身状态改变时主动发出通知。该模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,全部依赖于它的对象都获得通知并自动刷新。
三、状态模式(State Pattern)—— 该模式用于解决系统中复杂对象的状态转换以及不一样状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间能够进行转换,并且对象在不一样状态下行为不相同时,那就能够考虑使用状态模式了。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态能够灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,不管对于何种状态的对象,客户端均可以一致处理。
四、策略模式(Strategy Pattern)—— 该模式的使用场景是在项目中有多个可供选择的算法策略,客户端在其运行时根据不一样需求决定使用某一具体算法策略。在实现过程为,首先定义不一样的算法策略,而后客户端把算法策略做为它的一个参数。好比java中Collections.sort()方法了,它使用Comparator对象做为参数。根据Comparator接口不一样实现,对象会被不一样的方法排序。
五、职责链模式(Chain of Responsibility Pattern)—— 在该模式里,不少对象由每个对象对其下家的引用而链接起来造成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪个对象最终处理这个请求,这使得系统能够在不影响客户端的状况下动态地从新组织和分配责任。就如同android中TouchEvent事件的处理同样,它会被一层一层传下去,若是被处理的就不往下传了。
六、命令模式(Command Pattern)—— 该模式将一个请求封装成一个对象(参数+行为),使客户的不一样请求实现了参数化。大致结构是Command接口,Command*实现类,接收者Receiver(通常是个队列)。该模式是对行为进行封装的典型模式,解耦了发送者和接受者之间联系。 发送者调用一个操做,接受者接受请求执行相应的动做,由于使用Command模式解耦,发送者无需知道接受者任何接口。
七、访问者模式(Visitor Pattern)—— 封装一些做用于某种数据结构中的各元素的操做,它能够在不改变这个数据结构的前提下定义做用于这些元素的新的操做。访问者模式的优势是增长操做很容易,由于增长操做意味着增长新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增长新的数据结构很困难。若是数据结构不是很稳定,那访问者模式将不适用。
八、调停者模式(Mediator Pattern)—— 该模式包装了一系列对象相互做用的方式,使得这些对象没必要相互明显引用。从而使它们能够较松散地耦合。当这些对象中的某些对象之间的相互做用发生改变时,不会当即影响到其余的一些对象之间的相互做用。从而保证这些相互做用能够彼此独立地变化。典型的例子——电脑的CPU、显示器、内存、声卡、硬盘、光驱有相互联系的,也有不须要联系的。而主板就至关于调停者。若是没有主板,那么一个对象就要处理好几个与之联系的对象。而且因为联系的不一样,每一个对象都是如此,这种系统简称“过分耦合系统”……而有了主板(调停者),每个对象所要处理的对象就变成了单一的调停者,调停者知道如何跟全部的配件打交道,这样就简单多了。
九、备忘录模式(Memento Pattern)—— 在不破坏封装的条件下,将一个对象的状态存储起来并外部化,从而能够在未来合适的时候把这个对象还原到存储时的状态。实现方式是建立一个备忘对象的管理类,客户端只跟管理类耦合。如同Android系统中对Activity对象的状态保存同样。
十、迭代器模式(Iterator Pattern)—— 主要处理集合对象,该模式的思想是提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部结构。这也是java中用的最多的模式,Java的集合类均可实现迭代器模式,对集合里面的对象进行遍历。迭代器模式的优势是简化了复杂集合的遍历方式,封装性良好,用户只须要获得迭代器就能够遍历,而对于遍历算法则不用去关心。可是它的缺点也很明显,那就是不适合去处理比较简单的(像数组或者有序列表),使用迭代器方式去遍历简单的裂变反而较为繁琐,大如同List,咱们更愿意使用foreach循环去遍历。
十一、解释器模式(Interpreter Pattern)—— 该模式就是定义语言的规则,而且创建一个解释器来解释该规则的语义。若是一种特定类型的问题发生的频率足够高,那么就值得将该问题的各个实例表述为一个简单语言中的句子,天然也就须要构建一个解释器去解释这些句子来解决该类问题。解释器模式在实际的系统开发中使用的很是少,由于它会引发效率、性能以及维护等问题,一般的作法是使用其余工具甚至语言来完成这种类型的业务逻辑。
结束语:知识永远都不可能学完,可是若是你对知识进行更高层的认识而不是死记硬背,生活着任何一个点滴都能唤起你对这些知识的运用。