设计模式是前人根据经验总结出来的,设计模式不仅仅只是一种规范,更多的是一种设计思路和经验总结。
掌握好设计模式的目的只有一个:提高你高质量编码的能力,使用好设计模式就相当于是站在了前人的肩膀上。
在JDK的源码里,以及框架中间件的源码实现里,到处都是设计模式。
如果你想看懂框架源码,更加深入的了解技术的底层实现,掌握好设计模式就变得至关重要了@mikechen。
设计模式的目的
设计模式的目标:提升代码重用性、可读性、可扩展性、可靠性,还能降低系统中类与类之间的耦合度,使程序呈现高内聚低耦合的特性。
设计模式的价值,主要分为如下4点:
1.代码重用性
相同功能的代码不用多次编写
2.可读性
设计模式使程序易读,编程规范性,便于其他程序员的阅读和理解
3.可扩展性
设计模式能使编写的程序具有良好的可扩展性,满足系统设计的开闭原则。比如策略模式,就是将不同的算法封装在子类中,在需要添加新的算法时,只需添加新的子类,实现规定的接口,即可在不改变现有系统源码的情况下加入新的系统行为。
4.可靠性
当我们增加新的功能后,对原来的功能没有影响
设计模式常用7大原则
1.单一职责原则
对于类来说,一个类应该只负责一项职责
2.接口隔离原则
避免其实现类污染
3.依赖倒转(倒置)原则
1)高层模块不应该依赖底层模块,二者都应该依赖其抽象
2)抽象不应该依赖细节,细节应该依赖抽象
3)依赖关系传递的3中方式
- 接口传递
- 构造方法传递
- setter方法传递
4.里氏替换原则
子类尽量不要重写父类的方法
5.开闭原则
修改关闭,扩展开发
6.迪米特法则
一个对象应该对其他对象保持最少的了解
又叫最少知道原则,即一个类对自己依赖的类知道越少越好。
7.合成复用原则
尽量使用组合/聚合,不要用继承
设计模式的种类
1、创建型模式
用来描述 “如何创建对象”,它的主要特点是 “将对象的创建和使用分离”。
2、结构型模式
用来描述如何将类或对象按照某种布局组成更大的结构。
3、行为型模式
用来识别对象之间的常用交流模式以及如何分配职责。
5种创建型模式
创建型模式主要包括5 种模式:
1.单例模式
定义
创建某个类的实例,该类的实例在系统中只有这一份
单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。
应用场景
- 一个国家只有一个总统;
- 项目中用于读取配置文件的类;
- 数据库连接池,因为数据库连接池是一种数据库资源;
- Spring中,每个
Bean
默认都是单例的,这样便于Spring容器进行管理; - Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行
2.工厂模式
定义
工厂模式属于创建型设计模式,需要生成的对象叫做产品,生成对象的地方叫做工厂。
把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
应用场景
在任何需要生成复杂对象的场景,都可以使用工厂模式。
3.抽象工厂模式
定义
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类,每个生成的工厂都能按照工厂模式提供对象。
应用场景
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 在很多软件系统中需要更换界面主题或者一键换肤。
- DAO层支持多种类型的数据库,动态切换时。
- 不同操作系统代码差异化,可以切换不同操作系统时。
4.原型模式
定义
原型模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
应用场景
- 类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。
- 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
5.建造者模式
定义
建造者模式将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成不同复杂对象。
应用场景
- 建造者模式一般用在构建流程或者组成部件固定的场合,将这些部件分开构建成为组件对象,再将这些组件对象整合成为目标对象。
- 比如创建一个旅游产品,旅游产品里面有机票,酒店,门票,保险等等,行程定制师可以根据你的要求,组装成一个你满意的产品。
- 生活中的应用场景,比如汽车中的方向盘,发动机,车架,轮胎等等部件也是多种多样的。
7种结构型模式
结构型模式主要包含7种模式:
1.适配器模式
定义
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
目的是兼容性,让原本因接口不匹配,不能一起工作的两个类可以协同工作。
应用场景
- 封装有缺陷的接口设计
- 统一多个类的接口设计,比如一个支付系统,有三种不同的支付方式,微信支付、支付宝支付、网银支付,这三种支付的实现方法都不一样,那么我们可以用适配器模式,让他们对外具有统一的方法,这样,我们在调用的时候就非常的方便。
- 兼容老版本的接口,这个在我们系统升级中经常会用到。
2.桥接模式
定义
桥接模式把 抽象(Abstraction) 与 行为实现(Implementation) 分离开,保持各部分的独立性以及功能扩展。
应用场景
JDBC连接数据库时,利用驱动来桥接,这就是典型的桥接模式应用。
3.装饰模式
定义
动态的将新功能附加到对象上,就像打包一个快递,一层一层地给物品添加外层包装。
应用场景
- 扩展一个类的功能。
- 动态增加功能,动态撤销。
4.组合模式
定义
依据树形结构来组合对象,用来表示部分以及整体层次,比如:学校、院、系的关系。
应用场景
- 组合模式非常适合有递归迭代性质的结构或者逻辑。即结构上存在树型或者包含关系,逻辑上”整体”和”部分”的行为和状态的对外表现是一致的,或者是类似的。
- 比如目录和文件,目录可以只包含子目录,也可以只包含文件,当然可以同时包含子目录和文件,而子目录又可以包含子目录或者文件。
5.外观模式
定义
外观模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
应用场景
- 为一个复杂的模块或子系统提供一个供外界访问的接口。
6.享元模式
定义
享元模式使用共享对象可以有效的支持大量细粒度对象的复用,比如:池化技术,数据库连接池 、线程池 等
应用场景
- 系统中存在大量的相似对象。
- 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对 象没有特定身份。
- 需要缓冲池的场景。
7.代理模式
定义
代理模式:封装目标对象,并添加额外的功能,对客户端提供更多更优的服务,分类:静态代理和动态代理。
应用场景
- 日志的采集
- 权限控制
- 实现aop
- Mybatis mapper
- Spring的事务
- 全局捕获异常
- Rpc远程调用接口
- 分布式事务原理代理数据源
11种行为型模式
行为型模式主要包含11种模式:
1.模板方法模式
定义
模板方法模式:定义了操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。
应用场景
- 多个子类有共同的方法,且逻辑基本相同
- 可以把核心的算法和重要的功能设计为模板方法,子类去实现相关细节功能
- 系统在进行重构或者是功能优化的时候可以将子类重复的代码抽离到父类中
2.命令模式
定义
命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
消除了 请求发送者 与 请求接收者 之间的耦合,对象之间的调用关系更加灵活,实现解耦。
应用场景
- 当一个应用程序调用者与多个目标对象之间存在调用关系时,并且目标对象之间的操作很类似的时候。
- 例如当一个目标对象内部的方法调用太复杂,或者内部的方法需要协作才能完成对象的某个特点操作时。
- 有时候调用者调用目标对象后,需要回调一些方法。
3.访问者模式
定义
访问者模式:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
应用场景
- 对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
4.迭代器模式
定义
迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示,提供一种遍历集合元素的统一接口。
应用场景
统一接口 : 为遍历 不同的 集合结构 , 提供统一接口
5.观察者模式
定义
当一个对象被修改时,则会自动通知依赖它的对象。
观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者发现,这么想来目标发生情况到观察者知道情况,其实是由目标将情况发送到观察者的。
应用场景
多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。
6.中介者模式
定义
中介者模式:是用来降低多个对象和类之间的通信复杂性,这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。
应用场景
- 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。
7.备忘录模式
定义
所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
应用场景
- 需要保存和恢复数据的相关状态场景
- Windows 里的 ctri + z
- IE 中的后退。
- 数据库连接的事务管理就是用的备忘录模式
8.解释器模式(Interpreter模式)
定义
解释器模式:这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
应用场景
重复发生的问题可以使用解释器模式
例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,但是非终结符表达式就需要制定了。在这种情况下,可以通过程序来一劳永逸地解决该问题。
9.状态模式
定义
我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
应用场景
- 行为随状态改变而改变的场景这也是状态模式的根本出发点,例如权限设计,人员的状态不同即使执行相同的行 为结果也会不同,在这种情况下需要考虑使用状态模式。
- QQ的不同状态可以用状态模式来处理,包括离线,登录中,在线和忙碌
10.策略模式
定义
利用面向对象的多态特点,引用的是抽象父类,当实际调用的时候是该对象的实体子类,从而调用不同的逻辑
应用场景
- 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
- 旅行的出游方式,选择骑自行车. 坐汽车,每一种旅行方式都是一个策略。
11.职责链模式(责任链模式)
定义
责任链模式:在这种模式中,通常每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
应用场景
- 多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定。
- JAVA WEB 中 Apache Tomcat 对 Encoding 的处理
- Struts2 的拦截器
- Servlet 的 Filter实现
以上就对23种设计模式做了一个完整的全面总结,希望对你所用!
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》