什么是设计模式?

“设计模式”这个术语最初(1977年)出现在建筑领域设计,1990年软件行业才开始开始讨论软件设计模式。
说明:

  1. 复杂系统设计或复杂问题解决方案,才会出现设计模式。
  2. 也就是说设计模式是前辈总结的解决复杂问题可复用的固定套路或经验总结。

定义:软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。

两大前提:

  1. 软件编程领域,解决复杂问题多使用“面向对象”的编程思想,固设计模式是面向对象思想下的产物,Java是最早最完善也是时间跨度最长的面向对象思想编程语言,固设计模式多由Java语言来体现;
  2. 特别说明,设计模式是一种解决问题的套路或经验总结,不仅仅适合面向对象编程,但以面向对象为主;
  3. 特别说明,面向对象编程不仅仅适用于Java,其他语言也可展现,但以Java未展现的巨多。

固,对于编程人员来说:
设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。

总结:

  • 设计模式是面向对象编程思想的产物
  • 设计模式一一种反复被使用和验证过的软件设计经验总结,是解决特定常见问题的一系列套路
  • 学习设计模式能提高编程能力,知行合一的过程中,也能升华人生的处事和处世
  • 避免过度设计,禁止为了设计模式而模式,大道至简,用设计模式是为了让系统更简单、更稳固,不要为了炫技而故意套用设计模式,此为大忌

我们常说的设计模式通常指:Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式、结构型模式和行为型模式。
但后人往往堆GOF做了补充,举个例子,Spring的MVC模式就不是设计模式,MVC是“观察者模式”和“策略模式”、“组合模式”三种经典模式的演变。

设计模式分类

通常我们说的设计模式是指23种Java设计模式,(实际可能大于23种设计模式,也不止Java语言,只是23种Java的设计模式有代表性)根据目的来分,可以分为三种:

  1. 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。
  2. 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构。
  3. 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责。

    创建型模式(五种)

    创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
  • 工厂方法模式(Factory):工厂创建对象(经典实现:很多框架初始化时都会创建一个工厂对象,用来加载资源)
  • 抽象工厂模式(Abstractfactory):抽象工厂实例创建对象,工厂可修改,灵活度高(经典实现:Struts2插件机制的核心实现就是BeanFactory这个抽象工厂。Spring IOC加载Bean,AOP创建Proxy)
  • 单例模式(Sington):适用于只需要一个对象的情况(经典实现:Tomcat中StringManager的错误处理机制)
  • 建造者模式(Builder):一步一步创建一个复杂的对象(经典实现:MyBatis中的SQLSession就是结合了Configure,executor等对象,以此来实现SQLSession的复杂功能)
  • 原型模式(Prototype):复制对象,包括深度复制和浅度复制,深度复制重建引用对象,浅度复制不创建(经典实现:java序列化)

    结构型模式(七种)

  • 适配器模式(Adapter):通过实现接口,依赖注入,继承等方式为不相关的实体建立关系(经典实现:Tomcat新版本连接器Coyote,就是通过为Connector适配建立了ProtocolHandler与Tomcat组件Connector的关联关系)

  • 装饰器模式(Decorator):创建包装对象修饰扩展被包装对象的功能(经典实现:IO家族中BufferedXxx)
  • 代理模式(Proxy):通过添加中间代理的方式限制,过滤,修改被代理类的某些行为(经典实现:Spring AOP核心实现,DataSource中为Connection创建代理对象,改变close方法的行为,使其从开始的关闭连接变成将连接还回连接池)
  • 外观模式(Facade):通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象。(经典实现:Tomcat中创建外观类包装StandardContext传给Wrapper,创建外观类包装Wrapper以ServletConfiguration的形式传给Servlet,以此来屏蔽不想让Servlet可见的那些Tomcat容器参数)
  • 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化(经典实现:JDBC驱动)
  • 组合模式(Composite):部分与整体,常用于表示树形结构
  • 享元模式(Flyweight):维护资源集合(经典实现:数据库连接池,避免重新开启数据库链接的开销)

    行为型模式(十一种)

  • 策略模式(Strategy):定义多个不同的实现类,这些类实现公共接口,通过调用接口调用不同实例得到不同结果(经典实现:Spring中Bean的定义与注入,Controller,Servcie,repository三层架构中只依赖上一层接口)

  • 模板方法模式(Template):父类定义公共方法,不同子类重写父类抽象方法,得到不同结果(经典实现:Tomcat生命周期中的init,SpringIOC上层类加载具体子类指定的配置文件)
  • 观察者模式(Observer):目标方法被调用,通知所有观察者(经典实现:Tomcat生命周期事件监听,Spring BeanPostProcessor实现 )
  • 迭代子模式(Interator):提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。(经典实现:集合迭代器)
  • 责任链模式(ChainOfResponsibility):链式依赖,依次调用(经典实现:Tomcat Valve)
  • 命令模式(Commond):Action定义具体命令,拦截器Invocation回调执行命令(经典实现:Struts2)
  • 备忘录模式(Memento):建立原始对象副本,用于存储恢复原始对象数据
  • 状态模式(Stage):通过改变状态,改变行为(经典实现:切换装载着不同配置信息的配置文件对象)
  • 访问者模式(Visitor):结构与操作解耦。灵活的操作,放入固定的结构中执行(经典实现:在SpringAOP的实现过程中首先会有一个ProxyCreator去创建切入点,通知之类的,然后创建一个抽象工厂将这些参数对象传递给抽象工厂,抽象工厂调用createAopProxy(this)来创建对象,传入不同的抽象工厂创建出不同的实体对象)
  • 中介者模式(Mediator):MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者
  • 解释器模式(Iterpreter):定义分别定义 + - * / 非终结符,组合不同的非终结符定义不同的表达式,维护繁琐

学习设计模式的方法

  1. 明确模式名称
  2. 模式对应的问题和应用场景
  3. 模式是怎么解决的,提供的解决方案是什么
  4. 效果,用了模式之后的优点

附录 23种设计模式

GoF的23种设计模式的功能

前面说明了 GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。

  1. 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
  2. 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
  3. 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
  4. 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
  5. 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
  6. 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
  7. 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
  8. 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
  9. 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。
  10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
  11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。
  12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
  13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
  14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
  15. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
  16. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
  17. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
  18. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
  19. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
  20. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
  21. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
  22. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
  23. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

    一句话归纳设计模式

    | 分类 | 设计模式 | 简述 | 一句话归纳 | 目的 | 生活案例 | | —- | —- | —- | —- | —- | —- | | 创建型设计模式
    (简单来说就是用来创建对象的) | 工厂模式(Factory Pattern) | 不同条件下创建不同实例 | 产品标准化,生产更高效 | 封装创建细节 | 实体工厂 | | | 单例模式(Singleton Pattern) | 保证一个类仅有一个实例,并且提供一个全局访问点 | 世上只有一个我 | 保证独一无二 | CEO | | | 原型模式(Prototype Pattern) | 通过拷贝原型创建新的对象 | 拔一根猴毛,吹出千万个 | 高效创建对象 | 克隆 | | | 建造者模式(Builder Pattern) | 用来创建复杂的复合对象 | 高配中配和低配,想选哪配就哪配 | 开放个性配置步骤 | 选配 | | 结构型设计模式
    (关注类和对象的组合) | 代理模式(Proxy Pattern) | 为其他对象提供一种代理以控制对这个对象的访问 | 没有资源没时间,得找别人来帮忙 | 增强职责 | 媒婆 | | | 外观模式(Facade Pattern) | 对外提供一个统一的接口用来访问子系统 | 打开一扇门,通向全世界 | 统一访问入口 | 前台 | | | 装饰器模式(Decorator Pattern) | 为对象添加新功能 | 他大舅他二舅都是他舅 | 灵活扩展、同宗同源 | 煎饼 | | | 享元模式(Flyweight Pattern) | 使用对象池来减少重复对象的创建 | 优化资源配置,减少重复浪费 | 共享资源池 | 全国社保联网 | | | 组合模式(Composite Pattern) | 将整体与局部(树形结构)进行递归组合,让客户端能够以一种的方式对其进行处理 | 人在一起叫团伙,心在一起叫团队 | 统一整体和个体 | 组织架构树 | | | 适配器模式(Adapter Pattern) | 将原来不兼容的两个类融合在一起 | 万能充电器 | 兼容转换 | 电源适配 | | | 桥接模式(Bridge Pattern) | 将两个能够独立变化的部分分离开来 | 约定优于配置 | 不允许用继承 | 桥 | | 行为型设计模式
    (关注对象之间的通信) | 模板模式(Template Pattern) | 定义一套流程模板,根据需要实现模板中的操作 | 流程全部标准化,需要微调请覆盖 | 逻辑复用 | 把大象装进冰箱 | | | 策略模式(Strategy Pattern) | 封装不同的算法,算法之间能互相替换 | 条条大道通罗马,具体哪条你来定 | 把选择权交给用户 | 选择支付方式 | | | 责任链模式(Chain of Responsibility Pattern) | 拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。 | 各人自扫门前雪,莫管他们瓦上霜 | 解耦处理逻辑 | 踢皮球 | | | 迭代器模式(Iterator Pattern) | 提供一种方法顺序访问一个聚合对象中的各个元素 | 流水线上坐一天,每个包裹扫一遍 | 统一对集合的访问方式 | 逐个检票进站 | | | 命令模式(Command Pattern) | 将请求封装成命令,并记录下来,能够撤销与重做 | 运筹帷幄之中,决胜千里之外 | 解耦请求和处理 | 遥控器 | | | 状态模式(State Pattern) | 根据不同的状态做出不同的行为 | 状态驱动行为,行为决定状态 | 绑定状态和行为 | 订单状态跟踪 | | | 备忘录模式(Memento Pattern) | 保存对象的状态,在需要时进行恢复 | 失足不成千古恨,想重来时就重来 | 备份、后悔机制 | 草稿箱 | | | 中介者模式(Mediator Pattern) | 将对象之间的通信关联关系封装到一个中介类中单独处理,从而使其耦合松散 | 联系方式我给你,怎么搞定我不管 | 统一管理网状资源 | 朋友圈 | | | 解释器模式(Interpreter Pattern) | 给定一个语言,定义它的语法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子 | 我想说”方言“,一切解释权都归我 | 实现特定语法解析 | 摩斯密码 | | | 观察者模式(Observer Pattern) | 状态发生改变时通知观察者,一对多的关系 | 到点就通知我 | 解耦观察者与被观察者 | 闹钟 | | | 访问者模式(Visitor Pattern) | 稳定数据结构,定义新的操作行为 | 横看成岭侧成峰,远近高低各不同 | 解耦数据结构和数据操作 | KPI考核 | | | 委派模式(Delegate Pattern) | 允许对象组合实现与继承相同的代码重用,负责任务的调用和分配 | 这个需求很简单,怎么实现我不管 | 只对结果负责 | 授权委托书 |