一、设计模式的分类
总体来说设计模式分为三大类,最为常用的也已经标注出来了,是需要我们重点掌握的。
- 创建型模式,共五种:单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。
- 结构型模式,共七种:装饰器模式、适配器模式、代理模式、组合模式、外观模式、桥接模式、享元模式。
- 行为型模式,共十一种:模板方法模式、观察者模式、中介者模式、解释器模式、迭代子模式、责任链模式、策略模式、命令模式、备忘录模式、状态模式、访问者模式。
二、设计模式的六大原则
总原则:开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。
1、单一职责原则
每个类应该实现单一的职责,否则就应该把类拆分。
2、里氏替换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科
历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
5、迪米特法则(最少知道原则)(Demeter Principle)
就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
6、合成复用原则(Composite Reuse Principle)
原则是尽量首先使用合成/聚合的方式,而不是使用继承。
三、设计模式:创建型模式
1、# 单例模式
确保在一个JVM中,该对象只有一个实例存在
2、# 工厂模式
- 简单工厂模式:一般就一个工厂类,它负责生产所有的对象(通过传入的参数不同生产不同对象)
- 工厂方法模式:通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建(一个工厂接口 + 多个具体工厂类)
3、# 工厂模式
- 抽象工厂模式:在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象
4、# 建造者模式
5、# 原型模式
不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。涉及到浅克隆和深克隆
四、设计模式:结构型模式
6、# 适配器模式
总结一下三种适配器模式的应用场景:
类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
7、# 装饰模式
如果你不想在修改原有类的基础上增强新的功能,那就使用装饰模式吧
8、# 代理模式
spring aop实践
9、# 门面模式
提供一个类用于客户访问它来间接访问我们的内部业务,我们的内部细节对于客户来说是透明的
10、# 桥接模式
11、# 组合模式
只要是树形结构,就可以考虑使用组合模式(如树形菜单,文件、文件夹的管理) 。
- 维护和展示部分-整体关系的场景, 如树形菜单、 文件和文件夹管理。
- 从一个整体中能够独立出部分模块或功能的场景
12、# 享元模式
本质:缓存共享对象,降低内存消耗
使用场景:Integer缓存,Long缓存、连接池等
五、设计模式:行为型模式
13、# 策略模式
该模式的核心思想是将不同的算法封装成独立的策略类,使得它们可以相互替换,而不影响客户端的使用。
14、# 模板方法模式
1.当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时,可使用模板方法模式。
2.当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。但其后果就是,只要算法发生变化,你就可能需要修改所有的类
15、# 观察者模式
java自带的观察者接口(java.util.Observer)和被观察者接口(java.util.Observable)
16、# 迭代器模式
使用java自带的java.util.Iterator基本够用了
17、# 责任链模式
责任链模式在Java中有许多应用场景,例如:
- 过滤器(Filter) :在Servlet中,过滤器就是使用责任链模式实现的。每个过滤器都可以决定是否处理请求,或者将其转发给下一个过滤器进行处理。
- 拦截器(Interceptor) :在Spring框架中,拦截器就是使用责任链模式实现的。拦截器可以对请求进行预处理或后处理,也可以将请求转发给下一个拦截器进行处理。
- 异常处理(Exception Handling) :在Java中,可以使用责任链模式来处理异常。首先,程序先尝试使用自定义的异常处理器来处理异常,如果该处理器无法处理异常,则将其转发给下一个处理器进行处理。
- 日志记录(Logger) :在Java中,可以使用责任链模式来记录日志。每个日志记录器都可以决定是否需要记录该日志,或者将其转发给下一个日志记录器进行记录。
18、# 命令模式
拿餐厅点餐为例,客人需要向服务员发出请求,但完全不知道做菜的厨师的姓名和联系方式,
也不知道厨师炒菜的步骤。但客人点菜后,便会有固定的厨师完成做菜的任务。
命令模式就会把客人订餐请求封装为Command对象,传到厨师手中。这就是实现了客人和厨师的耦合关系。
涉及到的角色:客人、服务员、厨师
动作:客人点菜、交给服务员、服务员让厨师做菜
服务员:接收来自客人的命令1(让厨师做土豆饭)
接收来自客人的命令2(让厨师做牛肉饭)
客户端Client完全不需要知道厨师做饭的细节,只需要知道自己点什么饭就可以了
19、# 备忘录模式
开发中常见的应用场景 :
- git、svn提交记录、回滚
- 普通软件中的,撤销操作
- 数据库软件中的,事务管理中的,回滚操作
- 软件升级中的版本记录、回滚
20、# 状态模式
21、# 访问者模式
22、# 中介者模式
通过引入一个中介者对象来降低多个对象之间的耦合度
23、# 解释器模式
解释器(Interpreter)设计模式定义了一套语法规则,并解释相应的语法,实现类似数学表达式计算的功能。