设计模式

设计模式

1. 常见的设计模式

1.1 工厂模式
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

1.2 单例模式
简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。

1.3 代理模式
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。代理就是一个Java对象代表另一个Java对象来采取行动。

1.4 策略模式
策略模式用于封装系列的算法,这些算法通常被封装在一个被称为Context的类中,客户端程序可以自由选择其中一种算法,或让Context为客户端选择一种最佳算法——使用策略模式的优势是为了支持算法的自由切换。
Jdk中的TreeSet和 TreeMap的排序功能就是使用了策略模式。

1.5 装饰者模式
装饰者模式动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。

2. 设计模式的的六大原则及其含义

2.1 单一职责原则Single Responsibility Principle
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
一个类承担的职责越多,它被复用的可能性就越小,而一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,就可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中。

2.2 开闭原则Open-Closed Principle
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
如果一个软件设计符合开闭原则,那么可以方便地对系统进行扩展,而且在扩展时无需修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。
为了满足开闭原则,需要对系统进行抽象化设计。抽象化是开闭原则的关键。

2.3 里氏替换原则Liskov Substitution Principle
所有引用基类的地方必须能透明地使用其子类的对象。
里氏代还原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用其子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。我们需要针对基类编程,而在程序运行时再确定具体子类。

2.4 依赖倒置原则Dependency Inversion Principle
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是真对实现编程。
依赖倒置原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明,参数类型声明,方法返回类型声明,以及数据类型的转换等;而不要使用具体的类来做这些事情。为了确保该原则的应用,一个具体类应该只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。
在实现依赖倒置原则是,我们需要针对抽象层编程,而将具体类的对象通过依赖注入的方式注入到其他对象中。

2.5 接口隔离原则Interface Segregation Principle
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需要知道与之相关的方法即可,不应该强迫客户依赖于那些它们不用的方法。

2.6 迪米特法则Law of Demeter
一个软件实体应当尽可能少地与其他实体发生相互作用。(只跟朋友说话!)
如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易。这是对软件实体之间通信的限制,此法则要求限制软件实体之间通信的宽度和深度。迪米特法则可以降低系统的耦合度,使类与类之间保持松散的耦合关系。

参考:
《设计模式的六大原则》
《白话设计模式六大原则》

3. 常见的单例模式以及各种实现方式的优缺点,哪一种最好,手写常见的单例模式

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类被称为单例类。
在很多实际场景中,我们希望某个类只能有一个实例化的对象。例如数据库连接池,日志对象等等,这个时候就需要单例模式。单例模式的核心思想是私有化构造器,防止其他类任意实例化该类。

3.1 延迟实例化(懒汉式单例模式)
只有在调用此类的getInstance()方法时才会实例化对象。
优点:只有真正需要使用时才会实例化对象,避免了可能的内存浪费。
缺点:必须通过加锁等方式来保证多线程的情况下单例,而且为了安全起见需要在加锁前后双重判断惟一的实例对象是否已经被生成。但加锁会影响效率。

3.2 立即创建对象(饿汉式单例模式)
当该单例类被加载时就创建惟一的单例对象。
优点:不需要加锁,执行效率很提高。
缺点:类加载时就初始化,如果对象很大,则会浪费内存。

3.3 登记式模式Holder
通过内部类来创建一个惟一的实例对象。
这个私有的静态内部类只有在外部类被调用时才会被加载,然后加载时直接产生singleton实例,而又不需要加锁。此模式具有上述两个模式的优点,屏蔽了它们的缺点,是最好的单例模式。

参考:
《单例模式的三种实现 以及各自的优缺点》

4. 设计模式在实际场景中的应用

4.1 适配器模式

  • java.util.Arrays#asList()
  • javax.swing.JTable(TableModel)
  • java.io.InputStreamReader(InputStream)
  • java.io.OutputStreamWriter(OutputStream)
  • javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
  • javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()

4.2 装饰者模式

  • java.io.BufferedInputStream(InputStream)
  • java.io.DataInputStream(InputStream)
  • java.io.BufferedOutputStream(OutputStream)
  • java.util.zip.ZipOutputStream(OutputStream)
  • java.util.Collections#checkedList|Map|Set|SortedSet|SortedMap

4.3 抽象工厂模式

  • java.util.Calendar#getInstance()
  • java.util.Arrays#asList()
  • java.util.ResourceBundle#getBundle()
  • java.sql.DriverManager#getConnection()
  • java.sql.Connection#createStatement()
  • java.sql.Statement#executeQuery()
  • java.text.NumberFormat#getInstance()
  • javax.xml.transform.TransformerFactory#newInstance()

4.4 观察者模式

  • java.util.EventListener
  • javax.servlet.http.HttpSessionBindingListener
  • javax.servlet.http.HttpSessionAttributeListener
  • javax.faces.event.PhaseListener

4.5 策略模式

  • java.util.Comparator#compare()
  • javax.servlet.http.HttpServlet
  • javax.servlet.Filter#doFilter()

参考:
《 JAVA中设计模式的实际应用》
《大家一起来说一说自己掌握的设计模式和在工作中的应用场景》

5. Spring中用到了哪些设计模式

5.1 简单工厂
Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。

5.2 工厂方法
Spring中的FactoryBean就是典型的工厂方法模式。

5.3 单例模式
Spring中的单例模式提供了一个全局的访问点BeanFactory,但没有从构造器级别去控制单例,这是因为Spring管理的是任意的Java对象。

5.4 适配器模式
Spring在Advisor链需要的是MethodInterceptor对象,所以每一个Advisor中的Advice都要适配成对应的MethodInterceptor对象。

5.5 装饰者模式
Spring中用到的装饰者在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。

5.6 代理模式
Spring的核心-AOP就是代理模式的增强版本,比如JdkDynamicAopProxy和CglibAopProxy。

5.7 观察者模式
Spring中观察者模式常用的地方是listener的实现。例如ApplicationListener。

5.8 策略模式
Spring中在实例化对象的时候会用到策略模式。

5.9 模板方法
Spring中的JdbcTemplate是模板方法的另一种理解。JdbcTemplate可以看成是模板方法不需要继承的一种实现方式。

参考:
《Spring-涉及到的设计模式汇总》
《Spring 框架的设计理念与设计模式分析》

6. MyBatis中用到了哪些设计模式

6.1 代理模式
mybatis框架调用mapper进行数据库操作时,获取的是mapper接口而不是实现类,用到的便是动态代理思想。

6.2 单例模式
框架中是由SQLSessionFactory创建SqlSession的,类似Jdbc中的connection。每次进行程序-数据库操作时都需要创建SQLSession,采用了单例模式生成的SQLSessionFactory来管理程序中的SqlSwsion。

6.3 装饰者模式
cache包下面的实现。以LoggingCache为例,一层层包装使得默认的cache实现PerpetualCache具有附加的功能,比如log功能。

6.4 工厂方法
SQLSessionFactory

6.5 模板方法
BaseExecutor,SimpleExecutor

6.6 适配器模式
Log,LogFactory

参考:
《Mybatis使用的设计模式》
《【Mybatis学习】框架中使用到的设计模式》

7. 你项目中有使用哪些设计模式

我项目中使用的比较多的,手写过静态工厂,用于生成Bean来模拟Spring框架的部分效果;然后也使用过装饰者模式和代理模式中的动态代理两种方法来分别作出过滤器增强request中的getParameter系列方法来解决中文乱码问题,也用到过观察者模式来进行用户的通知。

8. 说说常用开源框架中设计模式使用分析

此项是在过多过杂,而且本人使用的框架也有限,也就是ssh跟ssm而已,因此在这里直接给出地址,文章很不错,建议去看看。

参考:
《常用开源框架中设计模式使用分析(全)

9. 动态代理

你可能感兴趣的:(设计模式)