设计模式使用场景

Reading time ~10 minutes

此文章为原创文章,引用请标记文章出处: 设计模式使用场景

前言

  • 不必刻意使用设计模式,首先还是规范好代码(推荐文章-java编码规范1

  • 关注重用而非设计模式。也就是说设计模式是以重用为目的的,只要能做到重用,是否使用了某种设计模式并不重要

  • 开始不要考虑太多设计模式,等待初版完成后,后续发现有较多变化时,再做重构,在重构时考虑是否需要使用设计模块来适应变化。

  • 不正确地使用设计模式还不如不用,你在避免不正确使用的前提下慢慢用起来,就是正确使用了。

  • 设计模式是为了封装变化,让各个模块可以独立变化。精准地使用设计模式的前提是你能够精准的预测需求变更的走向,而精准的预测很难做到,需要深入的理解你的程序所在的领域的知识,了解用户使用你的软件是为了解决什么问题

设计模式使用场景

设计模式需要关注点不在实现,而应该在其概念和使用场景,而这里仅谈及常用的设计模式的使用场景,概念和实现都可以在任意一本设计模式书籍或网上都能找到

创建型

Singleton单例模式

  • 使用场景

1.当在系统中某个特定的类对象实例只需要有一个的时候,可以使用单例设计模式

  • 已用场景

1.数据库连接和Socket连接,需要保持同一时间只能有一个连接存在

2.java.lang.Runtime类

3.没有变量的工具类,也可以为了减少内存而使用单例

4.使用springmvc的使用,dao层和service层就是使用单例

Abstract Factory抽象工厂

  • 使用场景

1.创建产品家族,相关产品集合在一起使用的时候

2.想要提供一个产品类库,并只想显示其接口而不是实现时

  • 已用场景

1.java.sql.DriverManager,根据不同的驱动加载不同的驱动实现

2.java.lang.managerment.ManagementFactory 每种静态方法都会返回一个或多个表示Java 虚拟机组件的管理接口的平台 MXBean

Factory Method工厂方法

  • 使用场景

1.当子类型可能会有很多,以后需要不断增添不同的子类实现时

  • 已用场景

1.java.util.List中作为一个抽象接口工厂,iterator()接口方法返回一个迭代器接口Iterator(抽象产品),子类java.util.LinkedList、java.util.ArrayList实现了iterator()接口方法,返回具体的迭代器类型AbstractList$ListItr或AbstractList$Itr

2.jdk提供的jpa实现中,EntityManagerFactory 的 createEntityManager()方法可以传入不同的持久化单位创建不同的获得EntityManager对象

行为型

Iterator迭代器模式

  • 使用场景

1.需要对集合元素遍历,而不依赖于集合对象内部的实现细节(是数组还是列表方式)

2.支持对集合对象的多种遍历方式

3.为遍历不同的集合对象结构提供一个统一的接口

  • 已用场景

1.java.util.Iterator

Observer观察者模式

  • 使用场景

1.当一个系统中一个对象的改变需要同时修改其它对象内容,但是又不需要知道待改变的对象到底有多少个的时候

2.当一个对象的改变必须通知其它对象作出相应的变化,但是又不需要确定通知的对象是谁的时候

  • 已用场景

1.java.util.Observable(主题,被观察者)、java.util.Observer(观察者),使用推数据方式,setChanged()通知方法

Template Method模板方法

  • 使用场景

1.各子类中具有公共行为的时候,应该被提取出来并集中到一个公共父类中以避免代码重复

2.当需要控制子类扩展的时候,模板方法2里按顺序调用子类重载抽象父类的方法,这样就只允许在这些点进行扩展

  • 已用场景

1.java.util.Arrays数组中的sort()方法中,底层使用mergeSort()方法(模板方法)里通过compareTo方法来比较,而compareTo是需要我们实现的

2.spring的JdbcTemplate类,JdbcTemplate类通过模板设计模式帮助我们消除了冗长的代码,只做需要做的事情(即可变部分),并且帮我们做哪些固定部分,如连接的创建及关闭。

Command命令模式

  • 使用场景

1.当需要将”请求者”与”实现者”之间解耦

  • 已用场景

1.界面应用程序GUI,对于相同的按钮及菜单或弹出按钮只需共享此功能的一个实例即可

2.java.swing.Action,发送者是控件,接受者是事件函数

3.回调机制的面向对象设计需求、需要支持撤销和重做操作需求,以及类似于数据库回滚事务操作的需求

State状态模式

  • 使用场景

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变其行为,即这个改为的操作是在对象内部条件决定的

2.当状态的判断逻辑过于复杂时,为了消除这些If…else等条件选择语句,而通过把这些状态通过用一系列类来表示(即状态模式)

Strategy策略模式

  • 使用场景

1.如果不希望条件算法暴露给客户端应用程序,则把条件算法封装成策略算法

2.多个类的表现行为不同,需要在运行时动态选择具体要执行的行为的时候,即这个选择的操作是随不同外部环境采取不同行为的场合

  • 已用场景

1.java.util.concurrent.ThreadPoolExecutor线程池类就存在着4种预定义的处理程序策略

结构型

Composite组合模式

  • 使用场景

1.想表示对象的”部分-整体”层次结构,并可以在其中以相同的方式对待所有元素时

  • 已用场景

1.java.awt.Container类继承java.awt.Component类,java.awt.Container类中含有add添加组件方法,传入参数类型就是java.awt.Component类型,这使得java.awt.Container的所有子类都可以继承add方法,将不同的Component组件添加到list当中。

Decrator装饰模式

  • 使用场景

1.当我们需要为某个现有的对象动态地增加一个新的功能或职责的时候,可以考虑使用装饰者模式

2.当某个对象的职责经常发生变化或者经常需要动态地增加职责,避免为了适应这样的变化而增加继承子类扩展的方法时

  • 已用场景

1.java.io含有大量装饰者模式的应用,如:java.io.InputStream、java.io.OutputStream、java.io.Reader、java.io.Writer等

Facade外观模式

  • 使用场景

1.当子系统是相互依存的时候,需要层级化子系统,简化子系统之间的相依性的时候,可以使用外观模式

2.外观模式通过一个外观接口读/写子系统中各接口的数据资源,而客户可以通过外观接口读取内部资源库,不与子系统产生交互

  • 已用场景

1.java.util.logging.Logger类内部包含大量的其它辅助类,如果外部应用程序调用这些系统类则需要复杂的调用过程,而通过调用java.util.logging.Logger类就变得简单了。

Proxy代理模式

  • 使用场景

1.当我们进行某一项具体功能调用时,可以使用代理对象预先加载资源,初始化数据,初始化成功后再对真实对象进行调用,这样可以免去用户长时间的等待,提高系统访问效率

2.远程代理(RemoteProxy)为一个对象在不同的地址提供局部代理

3.虚拟代理(VirtualProxy),若一个对象的创建非常耗时,可通过代理对象去调用,在真实对象创建前,返回一个假的调用,等真实对象创建好了,再返回给客户端的就是一个真实对象的相应方法调用

4.保护代理(ProtectionProxy)控制对原始对象的访问

5.智能指引(SmartReference)取代简单的指针,在访问对象时执行一些附加操作

  • 已用场景

1.spring中的aop

2.jdk提供的动态代理(运行时生成代理对象),必须实现java.lang.reflect.InvocationHandler接口,这个接口的委派任务是在invoke()方法里实现的

Adapter适配器模式

  • 使用场景

1.软件系统结构需要升级或扩展,又不想影响原有系统的稳定运行的时候

2.转换类之间的差别不是太大的时候

3.想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作的时候

  • 已用场景

1.java.io.InputStreamReader和java.io.OutputStreamWriter

2.slf4j和log4j的关系,slf4j只是一个抽象层,你还需要绑定到一个实现上,这个实现就是log4j,而slf4j-log4j12充当适配器的角色负责提供slf4j-api到log4j的转换

参考资料

1.好书一本:《软件秘笈 设计模式那点事》

2.在知乎的一篇关于怎么用设计模式的帖子,点击访问

3.说明

  1. 一共三篇,从《java编码规范-上》这篇开始吧 

  2. 父类提供一个方法把由子类实现的抽象方法按照顺序调用,那个方法叫模板方法 

jdk-timer、spring-task、quartz的比较

这篇文章将简单介绍目前常用的定时任务框架! Continue reading

小岛经济学-读书笔记

Published on May 10, 2018

java常见的http请求库

Published on May 05, 2018