返回 导航

其他

hangge.com

Java - GoF设计模式详解1(总体介绍、JDK、Spring中的设计模式)

作者:hangge | 2023-02-17 09:30

一、GOF 设计模式

1,什么是 GOF 设计模式?

(1)GOFGang of Four)设计模式是由 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 四人在 1994 年出版的《设计模式:可复用面向对象软件的基础》一书中提出的。这本书提出了 23 种面向对象设计模式。这四个人常被称为 Gang of Four, 即四人组,简称 GoF
(2)根据面向对象设计模式要解决的问题(目的)将设计模式分为三类,分别为创建型、结构型和行为型,具体如下:
目的 描述 设计模式
创建型模式 用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。
  • 工厂方法模式(Factory Method
  • 抽象工厂模式(Abstract Factory
  • 建造者模式(Builder)
  • 原型模式(Prototype)
  • 单例模式(Singleton
结构型模式 用于描述如何将类或对象按某种布局组合成更大的结构。
  • 适配器模式(Adapter
  • 桥接模式(Bridge
  • 组合模式(Composite
  • 装饰器模式(Decorator
  • 外观模式(Facade
  • 享元模式(Flyweight
  • 代理模式(Proxy
行为型模式 描述类和对象怎样交互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。
  • 解释器模式(Interpreter
  • 模板方法模式(Template Method
  • 责任链模式(Chain of Responsibility
  • 命令模式(Command
  • 迭代器模式(Iterator
  • 中介者模式(Mediator
  • 备忘录模式(Memento
  • 观察者模式(Observer
  • 状态模式(State
  • 策略模式(Strategy
  • 访问者模式(Visitor

(3)根据面向对象设计模式主要用于类上还是对象上,又可以分为类模式、对象模式:

2,各模式基本介绍

(1)工厂方法模式Factory Method):提供了一种延迟创建类的方法,使用这个方法可以在运行期由子类决定创建哪一个类的实例。简单来说就是父类定义一个创建对象的接口,但由子类决定需要实例化哪一个类。
提示java.util.Collection 接口中定义了一个抽象的 iterator() 方法,该方法就是一个工厂方法。

(2)抽象工厂模式Abstract Factory):提供了一个接口来创建一系列具有相似基类或相似接口的对象。简单来说工厂父类提供一个创建产品族的接口,每个子类可以创建一系列相关或者相互依赖的对象,而无需指定它们具体的类。
提示Java.sql 包中的 Connection 类就使用了抽象工厂模式。

(3)建造者模式Builder):可以把复杂对象的创建与表示分离,使得同样的创建过程可以创建不同的表示。建造者模式与抽象工厂模式非常类似,但建造者模式是逐步地构造出一个复杂对象,并在最后返回对象的实例。
提示JDKStringBuilderStringBuffer 类使用了建造者模式;MyBatisSqlSessionFactoryBuiler 类用到了建造者模式。

(4)原型模式Prototype):用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。用这种方式创建对象非常高效,根本无须知道要创建对象的确切类以及如何创建等细节。
提示:在 Spring 中,当一个 Bean 被配置为原型作用域时,使用原型模式来创建对象。这就类似于使用原型模式来创建对象。

(5)单例模式Singleton):确保一个类只有一个实例,并且提供了对该类的全局访问入口,它可以确保使用这个类实例的所有的对象使用相同的实例。
提示JDK 中的 java.lang.Runtime 类、java.awt.Desktop 类、java.util.logging.Logger 类都是单例类;Spring 中无论使用注解,还是 xml 配置的 bean,如果没有指定 scope 属性,默认都是使用单例模式。

(6)适配器模式Adapter):可以解决系统间接口不相容的问题。通过适配器可以把类的接口转化为用户所希望的接口,从而提高复用性。
1,JDK 中的适配器模式:
  • InputStreamReaderOutputStreamWriter
  • Arrays.asList() 方法
  • Collections.enumeration() 方法
2,Spring 中的适配器模式:
  • Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式
  • Spring MVC 中的处理器适配器(Handler Adapter)、处理器映射器(Handler Mapping)使用了适配器模式

(7)桥接模式Bridge):把类的抽象部分同实现部分分离开来,这样类的抽象和实现都可以独立地变化(从而实现接口与实现分离)。
提示JDK 中的 JDBC 就使用了桥接模式;Spring 框架中的日志处理系统使用了桥接模式的思想。

(8)组合模式Composite):又叫部分整体模式,该模式将对象组合成树形结构以表示“整体-部分”的层次结构,使用户对单个对象和组合对象的使用具有一致性。
提示Java 的集合类 HashMap 就使用了组合模式;Mybatis 在处理动态 SQL节点时,应用到了组合设计模式。

(9)装饰模式Decorator):又叫装饰器模式、装饰者模式、包装模式(Wrapper),它可以在不改变对象结构的情况下,动态地给该对象添加新的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
提示JDK I/O 标准库使用到了装饰者模式;Spring 中类含有 WrapperDecorator 的类使用了装饰器模式;MyBatisorg.apache.ibatis.cache.decorators 包里的都是 Cache 接口的装饰类。

(10)外观模式Facade):又叫作门面模式,是一种通过为多个复杂的子系统提供一个统一的高层接口,从而使这些子系统更容易使用的模式。外观模式有助于将子系统与客户端分离,并降低子系统与客户端之间的耦合度。
提示SLF4JSimple Logging Facade for Java)即 Java 简单日志门面,是通过门面模式来实现。

(11)享元模式Flyweight):又叫做蝇量模式,指运用共享技术实现大量细粒度对象的复用,从而节省创建对象所需要分配的空间,以减少内存占用和提高性能。
提示JDK 中的 IntegerLongShortByte 等包装器类型利用了享元模式来缓存 -128 127 之间的数据;String 类使用了享元模式来维护字符串常量池;在数据库连接池的实现中,可以通过使用享元模式来共享数据库连接。

(12)代理模式Proxy):是为目标对象提供一种代理,从而能够在不改变目标对象的情况下,对目标对象的访问进行控制。
提示:在 JDK 中,Java 的动态代理、远程方法调用(RMI)是使用代理模式实现的;Spring AOP 是通过代理机制实现的。

(13)解释器模式Interpreter):给定一种语言,定义它的文法表示,并定义一个解释器,该解释器根据文法表示来解释语言中的句子。
提示Java 中的解释器模式在 javax.el 包中实现;Spring 框架中 SpelExpressionParser 使用到了解释器模式。

(14)模板方法模式Template Method):该模式在抽象类定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
1,JDK 中的模版方法模式:
  • java.util.AbstractListjava.util.AbstractSetjava.util.AbstractMap 等抽象类,它们都有一个模板方法 size(),它定义了计算集合大小的通用算法。
  • java.io.InputStreamjava.io.OutputStreamjava.io.Reader、java.io.Writer 等抽象类,它们都有一个模板方法 close(),它定义了关闭流的通用算法。
  • java.util.Comparator 接口,它有一个模板方法 compare(),它定义了比较两个对象的通用算法。
  • java.util.concurrent.Callable 接口,它有一个模板方法 call(),它定义了执行任务的通用算法。
2,Spring 中的模版方法模式:
  • JdbcTemplateRestTemplateJpaRepositoryMongoTemplateHibernateJpaVendorAdapterAbstractRoutingDataSourceAbstractJmsListeningContainer 等常用类都提供了一组抽象方法,然后允许子类实现这些方法,提供具体的实现逻辑。

(15)责任链模式Chain of Responsibility):把可以响应请求的对象链接起来,并在链中传递请求,直到有一个对象处理这个请求。从而保证多个对象都有机会处理请求,减少请求的发送者与接收者之间的耦合。
提示java.util.logging 包中的日志系统使用了责任链模式;Spring MVC 中的拦截器(Interceptor)、Spring AOP 中的切面(Aspect)、Spring 的事件传递机制(ApplicationEvent)使用了责任链模式。

(16)命令模式Command ):提供了一种将请求封装成对象的方法,从而使您可以用不同的请求对客户进行参数化。
提示:在 JDK 中,命令模式通常用于实现 GUI 组件的事件处理和菜单项的操作;Spring 中的事务管理、异步处理功能、调度任务功能、以及 JdbcTemplate 类都使用了命令模式。

(17)迭代器模式Iterator):提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
提示JDK 中的迭代器模式用在了 java.util.Iterator 接口和 java.util.Enumeration 接口中;Spring Framework 在内部一些地方也使用了迭代器模式。

(18)中介者模式Mediator):用一个中介者对象封装一系列对象交互,以防止这些对象直接交互,从而使这些对象耦合松散,并且可以独立地改变它们的交互。
1,JDK 中的中介者模式:
  • JDK java.util.Timer 类中,使用了中介者模式来管理定时器任务。
  • JDKjava.util.concurrent.Executor 接口和 java.util.concurrent.ExecutorService 接口中,使用了中介者模式来管理线程池。
2,Spring 中的中介者模式:
  • Spring 中,中介者模式可以通过使用 SpringApplicationContext 来实现。
  • Spring 提供了对 JMS 的支持,可以方便地在 Spring 应用中使用 JMS 来实现中介者模式。

(19)备忘录模式Memento):又称快照模式,或者令牌模式。指在不破坏封装性的前提下,将一个对象的内部状态存储在另一个对象中,这样以后就可将该对象恢复到原先保存的状态。
 
(20)观察者模式Observer):又叫做“发布-订阅模式”或者“模型-视图模式”。该模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
1,JDK 中的观察者模式:
  • 我们可以使用 JDK 中的 java.util.Observable 类和 java.util.Observer 接口实现了观察者模式。
  • JDK 中的 java.util.EventListener 是一个标记接口,用于定义事件侦听器类。它常用于观察者模式的实现。
  • javax.swing 库中,观察者模式通常用于处理 GUI 事件。
2,Spring 中的观察者模式:
  • Spring 事件机制使用观察者模式来传递事件和消息。
  • Spring Web MVC 使用观察者模式来处理 HTTP 请求和响应。

(21)状态模式State):允许一个对象在其内部状态改变的时候改变它的行为,这个对象看起来像是改变了其类。
提示:在 JDK 中的 java.util.Iterator 接口使用了状态模式;Spring Statemachine 是一个基于状态模式的状态机框架;Spring Batch 通过使用状态模式来管理批处理作业的状态。

(22)策略模式Strategy):定义一系列的算法,把它们封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的用户而变化。
提示JDK 中的 java.util.Collections 类使用了策略模式;java.util.concurrent.ThreadPoolExecutor 类也使用了策略模式来处理不同的任务执行策略;Spring 中的事务管理使用了策略模式;Spring 使用了策略模式来实现不同的 AOP 代理创建策略。

(23)访问者模式Visitor):将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使得在不改变各元素类的前提下定义作用于这些元素的新操作。访问者模式符合单一职责原则和开闭原则。
提示JDKNIO 模块下的 FileVisitor 接口提供了递归遍历文件树的支持,使用了访问者模式;Spring 中的 BeanDefinitionVisitor 类用于遍历和修改 bean 定义,就使用到了访问者模式。

附:面向对象设计原则(七大原则)

    对于面向对象软件系统而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题。在面向对象设计中,代码的可重用性和可维护性是以设计原则为基础的。常用的面向对象原则就包括七种:
  • 单一职责原则Single Responsibility Principle):设计目的单一的类。就是一个类应该只负责一个职责
  • 开放-封闭原则开闭原则)(Open Closed Principle):对扩展开放,对修改封闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。提倡一个类一旦开发完成,后续增加新的功能就不应该通过修改这个类来完成,而是通过继承,增加新的类。
  • 李氏Liskov替换原则Liskov Substitution Principle):子类可以替换父类。即一个软件系统中所有用到一个类的地方都替换成其子类,系统应该仍然可以正常工作。这个原则依赖面向对象的继承特性和多态特性。
  • 接口隔离原则Interface Segregation Principle):使用多个专门的接口比使用单一的总接口要好。
  • 依赖倒置原则Dependence Inversion Principle):要依赖于抽象,而不是具体实现;针对接口编程,不要针对实现编程。
  • 组合重用原则Composite Reuse Principle):要尽量使用组合,而不是继承关系达到重用目的。
  • 迪米特Demeter原则最少知识法则)(Law of Demeter):一个对象应当对其他对象有尽可能少的了解。一个软件实体应当尽可能少地与其他实体发生相互作用。
评论

全部评论(0)

回到顶部