设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)
设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)模式分类 & 传送门 & 比照维度说明
设计准则:设计模式(总纲)
创立型:单例模式 简单工厂模式 工厂方法模式 笼统工厂模式 建造者模式 原型模式
结构型:代理商模式 适配器模式 装饰器模式 桥接模式 组合模式 享元模式 外观模式
行为型:?观察者模式 模板方法模式 命令模式 状态模式 职责链模式 解释器模式 中介者模式 访问者模式 策略模式 备忘录模式 迭代器模式
以上便是设计模式的分类以及各个模式的传送门,可以看到其中行为型模式的个数为最多,结构型次之,创立型设计模式最少。
在写这篇文章的时候,LZ考虑的最多的一个问题就是,从哪几个维度去比照设计模式能让大家更加清楚的看出各个设计模式的区别与联络,思来想去,LZ决定从以下几个维度去比照设计模式。
设计准则:形容每个设计模式都遵循了哪些设计准则,破坏了哪些设计准则。
常用场景:形容各个设计模式大部分情况下,都会在哪些场景下出现。
使用概率:主要指在普遍的工作当中,该设计模式出现的频率,若是类库或者是开源框架提供的功能中包含该模式,则也会计算其频率。
复杂度:特指一个设计模式在实现的时候的复杂度,主要的衡量标准是类的数量、类之间的耦合关系。
变化点:设计模式很大的一个意义在于容纳变化,掌握一个设计模式的变化点是非常重要的一件事。
选择关键点:入选择使用一个设计模式的时候,指出最关键的选择点在哪里。
逆鳞:龙有逆鳞,不可触摸,同样的,设计模式也有逆鳞,有些地方是不能碰的。
相关设计模式:与其它设计模式的关系。
创立型设计模式
单例模式
设计准则:无
常用场景:应用中有对象需要是全局的且唯一
使用概率:99.99999%
复杂度:低
变化点:无
选择关键点:一个对象在应用中出现多个实例能否会引起逻辑上或者者是程序上的错误
逆鳞:在以为是单例的情况下,却产生了多个实例
相关设计模式
原型模式:单例模式是只有一个实例,原型模式每拷贝一次都会创造一个新的实例。
简单工厂模式
设计准则:遵循单一职责、违反开闭准则
常用场景:需要在一堆产品中选择其中一个产品
使用概率:99.99999%
复杂度:低
变化点:产品的种类
选择关键点:一种产品能否可根据某个参数决定它的种类
逆鳞:工厂类不能正常工作
相关设计模式
工厂方法模式:工厂方法模式是简单工厂模式的进一步笼统化,在这两者之间做选择,主要看将工厂进一步笼统化能否有必要,通常情况下,假如工厂的作用仅仅是用来制造产品,则没必要使用工厂方法模式。
工厂方法模式
设计准则:遵循单一职责、依赖倒置、开闭准则
常用场景:一种场景是希望工厂与产品的种类对用户端保持透明,给用户端提供一致的操作,另外一种是不同的工厂和产品可以提供用户端不同的服务或者功能
使用概率:60%
复杂度:中低
变化点:工厂与产品的种类
选择关键点:工厂类和产品类能否是同生同灭的关系
逆鳞:无
相关设计模式
笼统工厂模式:工厂方法模式与笼统工厂模式最大的区别在于,在工厂方法模式中,工厂创造的是一个产品,而在笼统工厂模式中,工厂创造的是一个产品族。
笼统工厂模式
设计准则:遵循单一职责、依赖倒置、开闭准则
常用场景:需要一个接口可以提供一个产品族,且不必知道产品的具体种类
使用概率:30%
复杂度:中
变化点:工厂与产品的种类
选择关键点:产品族能否需要一起提供,且能否有一致的接口
逆鳞:无
相关设计模式
建造者模式:两者都是建造一批对象或者者说产品,不同的是两者的目的和实现手段,在建造者模式中,是为了复用对象的构建过程而定义了一个指挥者,而在笼统工厂模式中,是为了提供一个这批对象的创立接口而定义了笼统工厂接口。
建造者模式
设计准则:遵循单一职责、开闭准则
常用场景:需要构建一批构建过程相同但表示不同的产品,而构建过程非常复杂
使用概率:10%
复杂度:中
变化点:产品的表示
选择关键点:各个产品的构建过程能否相同
逆鳞:指挥者不能正常工作
原型模式
设计准则:无
常用场景:需要在运行时动态的创立指定实例种类的对象,或者是需要复用其状态
使用概率:10%
复杂度:中低
变化点:无
选择关键点:创立出来的对象能否可以立即投入使用
逆鳞:在以为是深度拷贝的情况下,却未实现深度拷贝
结构型设计模式
代理商模式
设计准则:表现功能复用
常用场景:需要修改或者屏蔽某一个或者若干个类的部分功能,复用另外一部分功能,可使用静态代理商,若是需要阻拦一批类中的某些方法,在方法的前后插入少量一致的操作,假设这些类有一致的接口,可使用JDK的动态代理商,否则可使用cglib
使用概率:99.99999%
复杂度:中高
变化点:静态代理商没有变化点,动态代理商的变化点为具备相同切入点的类
选择关键点:静态代理商选择的关键点是能否要复用被代理商的部分功能,动态代理商选择的关键点在于是否在将被代理商的这一批类当中,找出相同的切入点
逆鳞:切入点的不稳固
相关设计模式
适配器模式:对于适配器模式当中的定制适配器,它与静态代理商有着类似的部分,二者都有复用功能的作用,不同的是,静态代理商会修改一部分原有的功能,而适配器往往是一律复用,而且在复用的同时,适配器还会将复用的类适配一个接口
适配器模式
设计准则:遵循开闭准则、表现功能复用
常用场景:需要使用一个类的功能,但是该类的接口不符合使用场合要求的接口,可使用定制适配器,又或者者是有一个接口定义的行为过多,则可以定义一个缺省适配器,让子类选择性的覆盖适配器的方法
使用概率:40%
复杂度:中
变化点:无
选择关键点:定制适配器的选择关键点在于能否有更加优良的替代方案,缺省适配器的选择关键点在于接口中的方法能否可以不一律提供,且都有缺省方案
逆鳞:无
相关设计模式
装饰器模式:对于适配器模式中的定制适配器与装饰器模式,二者都是使用组合加继承的手段,不同的是,适配器模式的目的在于适配接口,装饰器模式的目的在于动态的增加功能,且可以叠加。
装饰器模式
设计准则:遵循迪米特、单一职责、开闭准则,破坏里氏替换,表现功能复用
常用场景:一个类需要动态的增加功能,且这些功能可以相互叠加
使用概率:99.99999%
复杂度:中
变化点:动态增加的功能或者者说装饰器
选择关键点:增加的功能能否需要动态组装
逆鳞:无
桥接模式
设计准则:遵循单一职责、迪米特、开闭准则,表现功能复用
常用场景:一个对象有多个维度的变化,需要将这些维度抽离出来,让其独立变化
使用概率:20%
复杂度:中高
变化点:维度的扩展与添加
选择关键点:能否可以将对象拆分成多个不相关的维度
逆鳞:无
组合模式
设计准则:遵循依赖倒置、开闭准则,破坏接口隔离
常用场景:当有一个结构可以组合成树形结构,且需要向用户端提供一致的操作接口,使得用户端操作忽略简单元素与复杂元素
使用概率:30%
复杂度:中
变化点:节点的数量
选择关键点:对外提供一致操作接口的结构能否可转化为树形结构
逆鳞:结构不稳固或者结构中的节点有递归关系
享元模式
设计准则:无
常用场景:少量状态相同的对象被大量的重复使用
使用概率:90%
复杂度:中
变化点:无
选择关键点:被共享的对象能否可以将外部状态提取出来
逆鳞:没有将外部状态提取完全
外观模式
设计准则:遵循迪米特
常用场景:一个子系统需要对外提供服务
使用概率:60%
复杂度:中
变化点:无
选择关键点:子系统对外提供服务能否需要依赖很多的类
逆鳞:子系统对外提供的服务的变化或者子系统本身的不稳固
相关设计模式
中介者模式:二者都是为了解决复杂的耦合关系,不同的是外观模式解决的是类之间复杂的依赖关系,中介者模式解决的是对象之间复杂的交互关系
行为型设计模式
观察者模式
设计准则:遵循迪米特、开闭准则
常用场景:需要将观察者与被观察者解耦或者者是观察者的种类不确定
使用概率:40%
复杂度:中
变化点:观察者的种类与个数
选择关键点:观察者与被观察者能否是多对一的关系
逆鳞:观察者之间有过多的细节依赖
模板方法模式
设计准则:破坏里氏替换,表现功能复用
常用场景:一批子类的功能有可提取的公共算法骨架
使用概率:80%
复杂度:中低
变化点:算法骨架内各个步骤的具体实现
选择关键点:算法骨架能否牢固
逆鳞:无
命令模式
设计准则:遵循迪米特、开闭准则
常用场景:行为的请求者与行为的解决者耦合渡过高
使用概率:20%
复杂度:中高
变化点:命令的种类
选择关键点:请求者能否不需要关心命令的执行只知道接受者
逆鳞:命令的种类无限制增长
相关设计模式
职责链模式:容易将二者关联在一起的起因是,二者都是为了解决请求或者者命令而存在的,而且二者都是为了将请求者与响应者解耦,不同的是命令模式中,用户端需要知道一个命令的接受者,在创立命令的时候就把接受者与命令绑定在一起发送给调用者,而职责链模式中,用户端并不关心最终解决请求的对象是谁,用户端只是封装一个请求对象,随后交给职责链的头部而已,也正由于这样,二者的实现方式,有着很大的区别
状态模式
设计准则:遵循单一职责、依赖倒置、开闭准则
常用场景:一个对象在多个状态下行为不同,且这些状态可互相转换
使用概率:20%
复杂度:中
变化点:状态的种类
选择关键点:这些状态能否经常在运行时需要在不同的动态之间相互转换
逆鳞:无
相关设计模式
策略模式:二者的实现方式非常类似,策略接口与状态接口,具体的策略与具体的状态以及二者都拥有的上下文,假如看它们的类图,会发现几乎一模一样,而二者不同的地方就在于,状态模式经常会在解决请求的过程中更改上下文的状态,而策略模式只是按照不同的算法解决算法逻辑,而且从实际场景来讲,顾名思义,状态模式改变的是状态,策略模式改变的是策略
职责链模式
设计准则:遵循迪米特
常用场景:一个请求的解决需要多个对象当中的一个或者几个协作解决
使用概率:15%
复杂度:中
变化点:解决链的长度与次序
选择关键点:对于每一次请求能否每个解决的对象都需要一次解决机会
逆鳞:无
解释器模式
设计准则:遵循单一职责
常用场景:有一种语言被频繁的使用
使用概率:0.00009%
复杂度:中高
变化点:语言的规则
选择关键点:被频繁使用的语言能否可用文法表示
逆鳞:语言的规则无限制增长或者规则十分不稳固
中介者模式
设计准则:遵循迪米特,破坏单一职责
常用场景:一个系列的对象交互关系十分复杂
使用概率:10%
复杂度:中
变化点:对象之间的交互
选择关键点:复杂的交互关系能否有共性可被中介者承担
逆鳞:中介者无法工作
访问者模式
设计准则:遵循倾斜的开闭准则
常用场景:作用于一个数据结构之上的操作经常变化
使用概率:5%
复杂度:高
变化点:数据结构之上的操作
选择关键点:数据结构能否稳固以及操作能否经常变化
逆鳞:数据结构的不稳固
策略模式
设计准则:遵循单一职责、依赖倒置、迪米特、开闭准则
常用场景:算法或者者策略需要经常替换
使用概率:60%
复杂度:中
变化点:策略的种类
选择关键点:用户端能否依赖于某一个或者若干个具体的策略
逆鳞:无
备忘录模式
设计准则:遵循迪米特、开闭准则
常用场景:需要在对象的外部保存该对象的内部状态
使用概率:5%
复杂度:中
变化点:无
选择关键点:能否可以在必要的时候捕捉到对象的内部状态
逆鳞:大对象的备份
迭代器模式
设计准则:遵循迪米特
常用场景:需要迭代访问一个聚合对象中的各个元素,且不暴露该聚合对象内部的表示
使用概率:99.99999%
复杂度:中
变化点:聚合对象的种类
选择关键点:用户端能否关心遍历的次序
逆鳞:无
相关设计模式
访问者模式:二者都是迭代的访问一个聚合对象中的各个元素,不同的是,访问者模式中,扩开展放的部分在作用于对象的操作上,而迭代器模式中,扩开展放的部分在聚合对象的种类上,而且二者的实现方式也有着很大的区别。
结束语
以上便是24种设计模式的各个特点与部分模式的比照,假如总结的过程当中有疏漏或者是错误,请各位不吝赐教,LZ感激不尽。
此外需要说明的是,上面的概率当中有的会出现99.99999%这样的数字,这是由于这个模式已经嵌入到JAVA类库或者是我们常用的开源框架当中(标注一下:LZ总结的主要针对WEB开发,android的开发LZ并未接触过,所以不包括在此列),比方迭代器模式,只需你使用过ArrayList或者者HashSet,LZ就认为这个模式被使用。这个使用频率从某种意义上讲,可以认为是该模式的重要程度,当然因为这个频率是LZ制定的,所以仅代表个人观点。
这里再针对设计模式的学习,给各位提一点点建议,仅供参考,请各位吸优排差,次序不分先后。
1、之前说过,学习设计模式除了努力之外还要靠缘分,所以假如有设计模式当时怎样看都不明白,可以暂且放下,之后说不定哪天你忽然之间就明白了。(此话并非虚言,LZ很屡次的顿悟常发生在上厕所、洗澡、回家路上等少量学习之外的时候。)
2、对于已经在工作的人来说,可以常思考一下,有没有哪个设计模式可以改善现有的系统架构,但不要轻易付诸实践。
3、学习设计模式之前,肯定要先整明白UML类图,什么关联,依赖,聚合,组合等等都得搞明白儿的,否则学习起来也仍然会很费劲。
4、对于初学者,肯定要在弄清楚标准的实现代码之后,写一个属于自己的例子,哪怕是比葫芦画瓢,而后仔细体会设计模式使用前后的差异,主要从扩展性和类(类包括用户端,而不仅仅指设计模式中的角色)的职责两个方面。
5、肯定要将设计模式的变化点搞清楚,这点非常重要,甚至重要程度高于设计模式的场景、实现方式以及类和对象之间的耦合关系,很多时候,设计模式的滥用就是由于变化点没搞清楚,以至于该变化的没变化,不该变化的经常变化,添加系统的负担。
6、设计模式不是一次性学习完即可以扔掉不看的东西,而是要经常回过头来看看,说不定每一次你都有不一样的体会,而且一般情况下,这些体会会越来越深刻,越来越透彻。
7、假如可能的话,多研究少量开源框架,去找找它们里面的设计模式。
LZ暂时也就只能想到这些,假如以后有想到再补充吧,各位假如有什么好的建议也可以与LZ分享一下。
到此为止,整个设计模式系列就真真正正的彻底结束了,当初写的时候也没想到自己可以真的坚持下来,虽说整整26篇文章不算多,但是LZ的确花费了大量的时间和精力,值得欣慰的是LZ本人也得到了巨大的收获,不仅仅是对设计模式的了解日益加深,而且还得了不少猿友的支持,让LZ对分享这一道路更加坚定。
以后的编程之路还很长,对于LZ来说,编程并不仅仅是工作,而是一份事业,它给了LZ荣誉、金钱、成就感等等很多东西,希望各位至少在年轻的时候不要被少量悲观化的观点所干扰,特别是对编程有着酷爱的猿友们,极致才能成就大道,凡是在一个领域有所成就者,大都是钻研了数十年的成果。
当然,人各有志,LZ无法左右他人,但LZ已经决定了自己的路,学火影里鸣人的一句话,“这就是我的忍道。”
作者:左萧龙
链接:https://www.songma.com/p/fc001d3ff364
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)