设计模式总结

Java设计模式

一共三种模式:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
行为型模式关注的是对象之间的通信,也就是描述多个类或者对象之间,通过协作共同完成一个任务。主要涉及的是 对象 和 算法之间职责的分配。
行为型模式分为两类:
类行为模式: 通过继承机制来在类间分派行为。 主要是通过多态来分配父类和子类的职责
对象行为模式: 通过组合或聚合,在对象间分派行为。通过对象关联等方式来分配类的职责。

开放封闭原则(Open Close Principle)
原则思想:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化
描述:一个软件产品在生命周期内,都会发生变化,既然变化是一个既定的事实,我们就应该在设计的时候尽量适应这些变化,以提高项目的稳定性和灵活性。
优点:单一原则告诉我们,每个类都有自己负责的职责,里氏替换原则不能破坏继承关系的体系。

里氏代换原则(Liskov Substitution Principle)
原则思想:使用的基类可以在任何地方使用继承的子类,完美的替换基类。
大概意思是:子类可以扩展父类的功能,但不能改变父类原有的功能。子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法,子类中可以增加自己特有的方法。
优点:增加程序的健壮性,即使增加了子类,原有的子类还可以继续运行,互不影响。

依赖倒转原则(Dependence Inversion Principle)
依赖倒置原则的核心思想是面向接口编程.
依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,
这个是开放封闭原则的基础,具体内容是:对接口编程,依赖于抽象而不依赖于具体。

接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
例如:支付类的接口和订单类的接口,需要把这俩个类别的接口变成俩个隔离的接口

迪米特法则(最少知道原则)(Demeter Principle)
原则思想:一个对象应当对其他对象有尽可能少地了解,简称类间解耦
大概意思就是一个类尽量减少自己对其他对象的依赖,原则是低耦合,高内聚,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。
优点:低耦合,高内聚。

单一职责原则(Principle of single responsibility)
原则思想:一个方法只负责一件事情。
描述:单一职责原则很简单,一个方法 一个类只负责一个职责,各个职责的程序改动,不影响其它程序。 这是常识,几乎所有程序员都会遵循这个原则。
优点:降低类和类的耦合,提高可读性,增加可维护性和可拓展性,降低可变性的风险。

单例模式

作用:单例模式的核心是保证一个类只有一个实例,并且提供一个访问实例的全局访问点。
实现方式 优缺点
饿汉式 线程安全,调用效率高 ,但是不能延迟加载
懒汉式 线程安全,调用效率不高,能延迟加载
双重检测锁式 在懒汉式的基础上解决并发问题
静态内部类式 线程安全,资源利用率高,可以延时加载
枚举单例 线程安全,调用效率高,但是不能延迟加载
说说你在哪些框架中看到了单例的设计
1.Spring中的Bean对象,默认是单例模式
2.相关的工厂对象都是单例,比如:MyBatis中的SqlSessionFactory,Spring中的BeanFactory
3.保存相关配置信息的都是单例,比如:MyBatis中的Configuration对象,SpringBoot中的各个XXXAutoConfiguration对象等
4.应用程序的日志应用,一般都会通过单例来实现
5.数据库连接池的设计也是单例模式

工厂模式

工厂模式的作用是帮助我们创建对象,我们不用自己来创建,根据需要创建的对象的复杂度我们可以把工厂模式分为简单工厂,工厂方法和抽象工厂。
1 简单工厂
  简单工厂模式又称为静态工厂方法,他可以根据不同的参数而返回不同的实例,简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
JDK中的简单工厂应用:DataFormat
简单工厂对于新增产品是无能为力的!不修改原有代码根本就没办法扩展!!!
2 工厂方法
  针对于简单工厂的短板,引出了工厂方法模式,定义一个用户创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化延迟到了其子类中。
简单工厂和工厂方法模式的对比

  • 简单工厂只有一个工厂,而工厂方法有多个工厂
  • 简单工厂不支持扩展,而工厂方法支持扩展,扩展的方式就是添加对应的工厂类即可
  • 简单工厂代码复杂度低,工厂方法代码复杂度高
    3 抽象工厂
      上面的两种方式实现的工厂都是生产同一大类的产品,如果要实现生产不同类型的产品这时我们就可以用抽象工厂模式来实现。
    三者的对比:
  • 简单工厂模式(静态工厂模式) :虽然某种程度不符合设计原则,但实际使用最多。
  • 工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展。
  • 抽象工厂模式:不可以增加产品,可以增加产品族!

建造者模式

实际开发中,我们所需要的对象构建时非常复杂,且有很多步骤需要处理时,这时建造者模式就很适合。比如MyBatis中的SqlSessionFactory对象的创建,我们不光要创建SqlSessionFactory本身的对象,还有完成MyBatis的全局配置文件和映射文件的加载解析操作,之后把解析出来的信息绑定在SqlSessionFactory对象中,直接参考MyBatis的代码即可,所以建造者模式的作用就是帮助我们解决了复杂对象的创建。
建造者模式和工厂模式的区别:

  • 关注的维度是不一样的
  • 工厂模式创建对象 new 出来
  • 建造者模式关注的是对象创建的本身

原型模式

在java中我们知道通过new关键字创建的对象是非常繁琐的(类加载判断,内存分配,初始化等),在我们需要大量对象的情况下,原型模式就是我们可以考虑实现的方式。   原型模式我们也称为克隆模式,即一个某个对象为原型克隆出来一个一模一样的对象,该对象的属性和原型对象一模一样。而且对于原型对象没有任何影响。原型模式的克隆方式有两种:浅克隆和深度克隆。
浅克隆 只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址
深度克隆 深复制把要复制的对象所引用的对象都复制了一遍。

代理模式

1.1 代理模式的作用
  代理模式的作用是通过代理对象来增强目标对象的功能。利用的是AOP横切的思想。
1.2 代理模式的实现方式
  代理模式的实现方式有三种:静态代理,动态代理(JDK动态代理和CGLIB动态代理)
  1.2.1 静态代理
  代理对象实现了目标对象的调用,同时增强了目标对象的功能。
  1.2.2 JDK动态代理
  上面的静态代理我们需要手动的创建一个对应的代理来实现,不是太灵活,针对目
  1.2.3 CGLIB动态代理
  如果目标对象实现了对应的接口我们可以通过JDK动态代理的方式来实现,但如果
  标对象没有实现任何的接口,这时我们只能通过CGLIB动态代理来实现了,这时我
  需要单独引入cglib的依赖对象有实现相关接口的情况,我们可以使用JDK动态代理。

适配器模式

2.1 适配器的作用
  适配器模式的作用是把两个不兼容的对象通过适配器能够连接起来工作。
2.2 具体案例分析
  以MyBatis中的日志模块为例来介绍。常见的日志框架有log4j,log4j2,slf4j,logbak等,但是每种日志框架中的日志级别都有差异。

装饰者模式

3.1 装饰者模式的作用
  装饰者模式又称为包装模式(Wrapper),作用是用来动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术, 无须通过继承增加子类就能扩展对象的新功能 。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
3.2 装饰者模式的应用
 装饰者模式的应用场景还是非常多的,比如

  • IO流中的FileInputStream,FileOutputStream等
  • Spring中的各种Wrapper
  • MyBatis中的缓存设计

3.3 比较 说明
优点 1. 扩展对象功能,比继承灵活,不会导致类个数急剧增加
2. 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
3. 具体构建类和具体装饰类可以独立变化,
用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
缺点 1. 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
2. 装饰模式易于出错,调试排查比较麻烦。

组合模式

4.1 组合模式的作用
  其实解决的是对象与对象之间的包含关系。也就是 部分-整体 的层次结构。
4.2 组合模式的应用
  组合模式在配置文件的加载解析中其实会用的相对比较多。比如SpringSecurity的配置文件。

门面模式

门面模式也称为外观模式,他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。
具体的例子比如:MyBatis中的SqlSession接口,对外提供了数据库操作的相关功能,具体的实现细节对调用者是隐藏的,这种模式在实际项目和框架中很频繁

桥接模式

桥接模式的出现是替代掉多层继承的问题。提高了系统的扩展性。
具体的应用比如JDBC中的DriverManager其实有用到桥接模式,不同的数据库厂商对应不同的驱动和连接。

享元模式

这个问题相对来说比较冷门,用到的也比较少,主要是针对内存这块的节省处理,如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存。
享元模式以共享的方式高效地支持大量细粒度对象的重用。
享元对象能做到共享的关键是区分了内部状态和外部状态。 • 内部状态 :可以共享,不会随环境变化而改变 • 外部状态 :不可以共享,会随环境变化而改变。

解释器模式

1.1 解释器模式的作用
  解释器模式在业务开发面是很少接触到的。主要的作用是定义的解释器来解析各种表达式,比如SQL语句,SPEL表达式,权限注解中的表达式 hasAnyRole(‘ROLE_ADMIN’)等。
1.2 解释器的应用
  比较常见的应用比如Spring中的针对SPEL表达式做的解析处理

模板模式

2.1 模板模式的作用
  模板模式是一种相对简单的设计模式。作用是在父类中固定程序的执行顺序,具体的实现在子类中实现。比如银行定义每个人去银行开户的流程,
取号
填写单子
等待
办理业务
结束
然后每个人来开户都会走这个流程,只是每个人的具体操作内容会有区别
2.2 模板模式的应用
模板模式的应用就比较多如下:
Servlet中的doGet和doPost方法
Spring中的JdbcTemplate
MyBatis中的Executor处理

责任链模式

3.1 责任链模式的作用
  将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象处理。
3.2 责任链模式的应用
  责任链模式的应用场景比较多,对大家来说印象比较深刻的应该是SpringSecurity中的处理请求的过滤器链了。
可以和面试官具体聊下SpringSecurity中的这块设计。当然还有一些其他的也可聊比如:
Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch.
Javascript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理采用观察者模式。
SpringMVC中,拦截器的调用也是典型的责任链模式
同样的Servlet中的过滤器链同样是责任链模式的实现。

观察者模式

4.1 观察者模式的作用
  建立对象与对象之间的依赖关系,一个对象发生改变时,会自动通知其他对象。这个场景中,发生改变的对象被称为观察目标,被通知的对象称为观察者。一个观察目标可以有多个观察者,而这些观察者之间可以没有联系,可以根据需要增加或删除观察者。
4.2 观察者模式的应用
  观察者模式在Java编程中用到最多的可能就是事件模块的处理,可以和面试官详细的聊下Spring的事件管理机制或者SpringBoot的事件处理机制。我们以SpringBoot的事件机制为例来说明。
https://blog.csdn.net/qq_38526573/article/details/122143258 单独通过一篇文章来说明事件的本质。

策略模式

5.1 策略模式的作用
  策略模式的作用就是我们想要实现某个目的,实现的方式可以有很多种,那么这里的每一种实现方式都可以称为一种策略。
  我们可以将每一种交通方式都封装为一个独立的类,这就是一种策略。为了保证策略的一致性,还可以用一个抽象的交通方式类 来 做交通方式的定义。
5.2 策略模式的应用
策略模式在实际开发中用到的同样会比较多。

  • AOP 中根据不同的策略可以通过JDK动态代理或者CGLIB代理来创建代理对象
  • Spring框架中的Resources接口,资源访问的策略
  • Servlet中的service方法,会根据客户端的不同提交方式来调用对应的doGet或者doPost方法来处理请求
  • Shiro中的多Realm认证中,根据我们不同的配置可以使用所有Realm认证通过或者其中一个认证通过等
  • SpringSecurity中的Authentication对象的存储方式

迭代器模式

6.1 迭代器模式的作用
场景:访问聚合对象中的各个元素的时候,比如链表的遍历。我们一般是将遍历的方法也放在链表类中。但是如果需要修改遍历方法,就需要修改链表类的代码,违背了开闭原则。
迭代器模式就是在客户访问和聚合类之间插入一个迭代器,这样就将聚合对象 和 遍历方法解耦了,并且对外隐藏其实现细节。
6.2 迭代器模式的应用
JDK中的List/Set集合中的迭代器

中介者模式

7.1 中介则模式的作用
  对象之间具有很强的关联性,而且有大量的相互调用,这种情况下,如果一个对象发生了变化,就需要追踪该对象关联的其他对象,并进行相应的处理,这就变得很复杂。而中介者模式,就是用一个中介者对象来封装一系列的对象交互,中介者使各对象不需要显式的相互引用,这就使得系统变得低耦合。
  假如没有总经理。下面三个部门:财务部、市场部、研发部。财务部要发工资,让大家核对公司需要跟市场部和研发部都通气;市场部要接个新项目,需要研发部处理技术、需要财务部出资金。市场部跟各个部门打交道。 虽然只有三个部门,但是关系非常乱。实际上,公司都有总经理。各个部门有什么事情都通报到总经理这里,总经理再通知各个相关部门。
7.2 中介则模式的应用

  • MVC模式中的C,控制器就是一个中介者对象,M和V都和C打交道
  • 代理对象中的invoke方法,客户端和目标对象都是通过invoke来打交到的。

状态模式

场景: 如果一个对象的行为会根据 其某个属性的变化而不同,那这个属性就可以被称为该对象的状态。这样的对象也被称为有状态对象(stateful)。如果这样的对象因为某些事件,其内部状态发生了改变,那么系统的行为也要随之发生变化的话,就可以使用状态模式。

命令模式

场景:请求的发送者和接收者之间解耦,让对象之间的调用关系更加灵活。发送者和接收者之间没有直接的引用关系,发送请求的对象只需要知道如何发送,而不必关心如何完成请求。

备忘录模式

场景:记录一个对象的内部状态,当用户后悔时能撤销当前的操作,是数据恢复到它原来的状态。比如我们编程的时候,ctrl+z 就是撤销当前操作,恢复到修改前的状态。又叫快照模式。

访问者模式

场景:有些集合对象中会有多种不同的元素,每种元素都有不同的访问者 和 处理方式。这种被处理的数据元素相对稳定,但是处理方式比较多样的情况,可以用访问者模式来处理。
访问者模式将数据结构中的各元素的操作分离出来,封装成独立的类,使其在不改变数据结构的前提下,可以添加作用于这些元素的新操作。为数据结构中的每个元素提供多种访问方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值