Java——23种设计模式

在这里插入图片描述

1. 什么是设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
设计模式基于面向对象设计原则。对接口编程而不是对实现编程,优先使用对象组合而不是继承。

使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。

设计模式一般有如下几个基本要素:模式名称、问题、目的、解决方案、效果、实例代码和相关设计模式,其中的关键元素包括以下四个方面:模式名称 ,问题 ,解决方案 ,效果 。

2. 设计模式的分类

  • 根据目的(模式是用来做什么的)可分为创建型,结构型和行为型三类:
    创建型模式:主要用于创建对象。
    结构型模式:主要用于处理类和对象的组合。
    行为型模式:主要用于描述类或对象如何交互和怎样分配职责。
  • 根据范围,即模式主要是处理类之间的关系还是处理对象之间的关系,可分为类模式和对象模式两种。类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是一种静态关系;对象模式处理对象间的关系,这些关系在运行时变化,更具动态性。

设计模式之间的关系
在这里插入图片描述
在这里插入图片描述

3. 设计模式的七大原则

  1. 开闭原则:对扩展开放、对修改关闭。
  2. 单一指责原则:一个类只做一件事。
  3. 依赖倒转原则:类似于ioc,采用接口编程。
  4. 迪米特原则:高内聚,低耦合。
  5. 接口隔离原则:应该使用多个接口,而不是用单一的总接口。
  6. 合成复用原则:尽量使用对象组合,而不是继承来达到复用目的。
  7. 里氏替换原则:子类可以扩展父类的功能,但不能改变原有的功能。

4. 创建型模式(5种)

4.1 单例模式(Singleton)

保证一个类只有一个实例,并提供一个全局访问点。
Java设计模式之单例模式

4.2 工厂模式(Factory)

把对象的创建功能交给工厂,达到解耦目的。

适合场景

  1. 无法预知对象确切类别及依赖关系时,可使用。
  2. 希望复用现有对象来节省系统资源,而不是每次都创建对象。

4.3 抽象工厂模式(Abstract Factory)

用于创建一系列相关的对象, 而无需指定其具体类

适合场景

  1. 如果代码需要与多个不同系列的相关产品交互,由于无法提前获取相关信息或未来扩展考虑,不希望代码基于产品的具体类来进行构建的情况下使用。
  2. 当有一个基于一组抽象方法的类,且其主要功能不明确时,可以使用。

用例:spring的BeanFactory。和其他任何用于创建对象但返回接口或抽象类的就是此模式。

搭配模式:策略模式

4.4 生成器模式(Builder)

定义一个类来简化复杂对象的创建(分步骤创建)。该类是为了构建另一个类的实例。

适合场景

  1. 避免“重叠构造函数”的出现。
  2. 当希望用代码创建不同形式的产品时使用。
  3. 比如订单系统,订单对象就是一个复杂对象,我们就可以build来做。

用例:SpringApplicationBuilder、StringBuilder

4.5 原型模式(prototype)

使你能够复制已有对象, 而又无需使代码依赖它们所属的类。

适合场景

  1. 创建一个对象的实例非常复杂且耗时时可以使用
  2. 例如我们的DTO、BO、DO、VO转换时可以使用

用例:spring的bean有单例模式singleton和原型模式prototype(scope=prototype)

5. 结构型模式(7种)

5.1 代理模式(Proxy)

Java设计模式之代理模式

代理控制着对于原对象的访问(不能直接访问原对象), 并允许在将请求提交给对象前后进行一些处理。

适合场景

  1. 用于保护原对象
  2. 用于增强原对象

用例:jdk的Proxy类

5.2 适配器模式(Adapter)

用于新接口和旧接口的适配,使接口不兼容的对象能够相互合作。
在这里插入图片描述
适合场景

  1. 希望使用某类,但与接口或其他代码不兼容时使用
    用例:springmvc的HandlerAdapter。例如xml转json,可以新增XmlJsonAdapter适配器类内进行转换

5.3 桥接模式(bridge)

将抽象和抽象的具体实现进行解耦,使得抽象和抽象的具体实现可以进行独立变化。并使用组合的方式将多维度的抽象方法联系在一起
在这里插入图片描述
适合场景

  1. 想要拆分或重组一个具有多重功能的庞杂类(例如多个能与数据交互的类)可使用。
  2. 想在几个纬度上扩展类。
  3. 想要在运行是切换不同实现方法。

5.4 组合模式(composite)

可以使用它将对象组合成树状结构,以表示“部分-整体”的层次结构, 并且能像使用独立对象一样使用它们。

让客户端看起来在处理单个对象和对象的组合是平等的,换句话说,某个类型的方法同时也接受自身类型作为参数。例如Map的putAll(Map)方法
在这里插入图片描述
适合场景

  1. 需要实现树状对象结构时。
  2. 希望客户端代码以相同方式处理简单和复杂元素时。
  3. 常用于递归操作的优化上

5.5 外观模式/门面模式(Facade)

为一组接口、抽象类或子系统提供简化的接口。并且要求一个子系统的外部与其内部的通信必须通过一个统一的Facade对象进行。

Facade模式提供一个高层次的接口,使得子系统更易于使用

适合场景

  1. 需要一个指向复杂子系统的直接接口,但使用的功能有限时。
  2. 子系统组织为多层结构时。
  3. 保护子系统的接口,可以使用门面模式只提供某些接口,不提供全部。
  4. 使用Dubbo,向外提供的服务就尽量采用门面模式,然后服务在调用各种service做聚合

实例

  1. tomcat的RequestFacade
  2. SLFJ日志就是门面日志

5.6 装饰模式(Decorator/Wapper)

你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。相当于动态的给一个对象附加额外的功能,因此它也是子类化的一种替代方法。(就是在不继承的情况下,扩展类的功能)

实例

  1. tomcat对request的包装ServletRequestWrapper
  2. 所有的io流包装类

5.7 享元模式(Flyweight)

它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。

简单来说就是使用缓存来减小对象的访问时间(使用共享技术实现元素的共享)

适合场景:程序必须支持大量对象且没有足够的内存容量时使用(共享变量)

实例

  1. 只要用到了缓存,基本都是在使用享元模式

6. 行为型模式(12种)

6.1 责任链模式(Chain of Responsibility)

将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

可以实现解耦。责任链中的对象是同一接口或抽象类的不同实现。
在这里插入图片描述
适合场景

  1. 程序需要用不同的方式处理不同请求,而且请求类型和顺序未知时。
  2. 当必须按照顺序执行多个处理者时。
  3. 如果所需处理者及其顺序必须在运行时进行改变时。

用例

  1. servler中Filter过滤器
  2. 拦截器等

6.2 命令模式(Command)

将命令包装在对象中,以便可以存储、传递到方法中,并像任何其他对象一样返回(以命令动作为类名)

命令模式可以把发出命令的责任和执行命令的责任分开。

适合场景

  1. 需要通过操作来参数化对象。
  2. 想要将操作放入队列中,本地执行操作或远程执行操作时,可以使用。
  3. 想要实现操作回滚功能时。

用例

  1. java.lang.Runnable
  2. javax.swing.Action

6.3 迭代器模式(Iterator)

让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。

提供一个统一的方式来访问集合中的对象。

适合场景

  1. 当集合背后时复杂的数据结构,希望对客户端隐藏时(处于便利性或安全性)
  2. 可以监视程序中重复的遍历代码时
  3. 希望遍历不同,甚至是无法预知的数据结构时。

用例

  1. Iterator
  2. Vector集合
  3. set集合

6.4 中介模式(Mediator)

能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。(用一个中介对象来封装一系列关于对象交互行为)

即使用一个中间对象来进行消息分发以及减少类之间的直接依赖
在这里插入图片描述
适合场景

  1. 当一些对象或其他对象紧密耦合难以对其进行修改时。
  2. 当组件过于依赖其他组件而无法在不同应用中复用时。
  3. 如果为了能在不同情景下复用一些基本行为,而导致需要被迫创建大量组件子类时。

用例

  1. mq使用的就是此模式
  2. MVC中的Controller
  3. Executor

6.5 备忘录模式(Memento)

允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

即生成对象状态的一个快照,以便对象可以恢复原始状态而不用暴露自身的内容。

在不破坏封装性的情况下,捕获并保存一个类的内部状态,可以利用该保存的状态实施恢复操作。

适合场景

  1. 当你需要创建对象状态快照来恢复其之前的状态
  2. 当直接访问对象的成员变量、get、set时导致封装被突破时

用例

  1. Date对象通过自身内部的一个long值来实现备忘录模式
  2. Serializable

6.6 观察者模式/发布订阅模式(Observer/Listener)

允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

适合场景

  1. 当一个对象的改变需要改变其他对象时,或实际对象时事先未知的或动态变化的时。
  2. 当应用中的一些对象必须观察其他对象时。

用例

  1. EventListener
  2. tomcat的LifeCycleListener
  3. 使用zookeeper作为观察者,例如分布式锁、服务发现等

6.7 状态模式(State)

能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。

允许您在运行时根据内部状态轻松更改对象的行为。
在这里插入图片描述
状态模式重点在各状态之间的切换从而做不同的事情,状态模式不同状态下做的事情不同。

状态模式封装了对象的状态,因为状态是跟对象密切相关的,它不能被重用

适合场景

  1. 如果对象需要根据自身当前状态进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更时。
  2. 如果某个类根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时。
  3. 当相似状态和基于状态转换中存在许多重复代码时

6.8 策略模式(Strategy)

它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换

即将一组算法封装成一系列对象。通过调用这些对象可以灵活的改变程序的功能
在这里插入图片描述
策略模式更侧重于根据具体情况选择策略,并不涉及切换。策略模式做的都是同一件事。

策略模式封装算法或策略,通过从Context中分离出策略或算法,我们可以重用它们。

适合场景

  1. 想使用对象中各种不同的算法变体,并希望在运行时切换算法时。
  2. 如果算法在上下文的逻辑中不是特别重要,使用该模式能将类的业务逻辑与算法实现细节隔离开来。
  3. 当类中使用了复杂条件运算符如:if else,以在同一算法的不同变体中切换时。

可以用策略模式和工厂模式优化程序中过多的if-else

6.9 模版模式(template)

在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

即让子类可以重写方法的一部分,而不是整个重写,你可以控制子类需要重写那些操作。
在这里插入图片描述
适合场景

  1. 只希望客户端扩展某个特定的算法步骤,而不是整个算法或其结构时。
  2. 当多个类的算法除了一些细微不同之外几乎完全一样时。

用例

  1. InputStream类的skip或read方法
  2. 我们可以做一个抽象类,某个方法需要子类来实现差异化

6.10 访问者模式(Visitor)

提供一个方便的可维护的方式来操作一组对象。它使得你在不改变操作的对象前提下,可以修改或者扩展对象的行为。

它能将算法与其所作用的对象隔离开来。虽然可以在不改变原有类结构的基础上不断添加新的功能。但是缺点是破坏了封装性

适合场景

  1. 需要对一个复杂的对象结构(如对象树)中所有的元素执行某些操作时。
  2. 可使用此模式来清理辅助行为的业务逻辑
  3. 当某个行为仅在类层次结构中的一些类中有意义,在其他类中没意义时。

6.11 空对象模式(Empty)

它允许抽象空对象的处理。

用例

  1. Collections类的emptyList()
  2. Collections类的emptyMap()
  3. Collections类的emptySet()

6.12 解释器模式(Interpreter)

通常描述为该语言定义语法并使用该语法来解释该格式的语句

用例

  1. Pattern类
  2. Normalizer类
  3. Format类

7. 总结

在这里插入图片描述

7.1 创建型模式(Creational Patterns)

创建型模式(都是用来帮助我们创建对象的),这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。主要包括:

  • 单例模式(Singleton Pattern):保证一个类仅有一个对象,并提供一个访问它的全局访问点。
  • 工厂模式(Factory Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化,FactoryMethod使一个类的实例化延迟到其子类。
  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。
  • 建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。

7.2 结构型模式(Structural Patterns)

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。主要包括:

  • 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使他们都可以独立地变化。
  • 装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。就扩展功能而言,Decorator模式比生成子类的方式更为灵活。
  • 组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构。Composite 使得客户对单个对象和复合对象的使用具有一致性。
  • 外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的接口。Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
  • 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象。
  • 代理模式(Proxy Pattern):为其他对象提供一个代理以控制对这个对象的访问。

7.3 行为型模式(Behavioral Patterns)

这些设计模式特别关注对象之间的通信。主要包括:

  • 模版方法模式(Template Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • 命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消的操作。
  • 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
  • 观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
  • 中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
  • 备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保持该状态,这样以后就可以将该对象恢复到保存的状态。
  • 解释器模式(Interpreter Pattern):定义一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
  • 状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
  • 策略模式(Strategy Pattern):定义一系列的算法,把它们一个个封装起来,并且使他们可相互替换。本模式使得算法的变化可以独立于使用它的客户。
  • 责任链模式(Chain of Responsibility Pattern):为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它。
  • 访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类别的前提下定义作用于这些元素的新操作。

7.4 J2EE模式

这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。

  • MVC 模式(MVC Pattern)
  • 业务代表模式(Business Delegate Pattern)
  • 组合实体模式(Composite Entity Pattern)
  • 数据访问对象模式(Data Access Object Pattern)
  • 前端控制器模式(Front Controller Pattern)
  • 拦截过滤器模式(Intercepting Filter Pattern)
  • 服务定位器模式(Service Locator Pattern)
  • 传输对象模式(Transfer Object Pattern)
    在这里插入图片描述
java设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 设计模式遵循的原则有6个: 1、开闭原则(Open Close Principle)   对扩展开放,对修改关闭。 2、里氏代换原则(Liskov Substitution Principle)   只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。 3、依赖倒转原则(Dependence Inversion Principle)   这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。 4、接口隔离原则(Interface Segregation Principle)   使用多个隔离的借口来降低耦合度。 5、迪米特法则(最少知道原则)(Demeter Principle)   一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。 6、合成复用原则(Composite Reuse Principle)   原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值