设计模式 精讲 在JDK、Spirng中的应用

设计模式

原则描述
开闭原则对扩展开放,对修改关闭。提高可维护性
里式替换原则子类尽量不要对父类的非抽象方法进行重写
依赖倒置原则高层不应该依赖低层,面向接口编程
单一职责类的职责尽量单一,高内聚
接口隔离接口的职责进行精简,高内聚
迪米特法则不要对陌生人说话,陌生指当前对象对另一个对象的交互不直接,要合作完成功能需要额外转换工作
合成复用原则尽量少用继承,多用聚合,降低耦合

单例模式

全局只需要一个实例。
有多种实现,推荐双重检查、静态内部类、枚举。
例如JDK的Runtime
项目中的应用:

  • 全局唯一的线程池
  • Jedis工具类中唯一一个连接

原型模式

以一个对象作为模型,克隆出相同的对象。当需要某个对象的副本时使用。例如JDK的ArrayList的clone方法是深拷贝。浅拷贝只需实现Cloneable接口,并重写clone方法,简单调用super.clone即可。深拷贝有两种,一种是所有字段和本类都实现了Cloneable接口,并重写clone方法,要递归执行字段的clone方法。另一种是所有字段和本类都实现了Serializable,通过ObjectOutputStream、和ObjectInputSteam来完成深拷贝。

简单工厂

一个工厂,根据不同输入,生产不同的产品。例如JDK中的抽象类Calendar的creatCalendar,就有很多if判断产生不同的具体Calendar

实际项目中的应用:
需求:我们有很多支付方式,比如阿里支付、微信支付等等,客户端传来支付方式的id。
应用:各种支付实现支付接口。支付工厂中有个哈希表来存放id到支付方式对象,一个静态方法根据传入的id返回支付方式对象。

优点:一个类就能生产许多产品
缺点:当要增加或减少产品时需要修改代码

工厂方法

定义一个抽象方法,用于生产同一等级的产品,由子类对其实现生产不同的产品。例如JDK中的Collection的iterator(),ArrayList,ArrayBlockingQueue都实现了iterator()方法,生产不同的Iterator
优点:对扩展开放,对修改关闭
缺点:产品多时类很多

抽象工厂

定义一个抽象类,抽象类中有多个抽象方法,可以生产不同等级的产品,就是一个产品族。子类实现抽象类,生产产品族。例如JDK中用于数据库的Connection,定义生产Statement、PreparedStatement、CallableStatement的抽象方法。不同的数据库,就需要子类实现Connection。
优点:一个工厂能生产不同等级的产品
缺点:当要增加产品或删除产品时,所有子类都有修改

建造者模式

产品有固定的结构,由多个部件构成,每个部件可以选择不同具体实现,且构造产品有一定的步骤。这就可以用建造者模式,由建造者执行一定的步骤来构造产品,期间可以选择产品的具体组件。将产品的表示与构造分离开来。例如JDK中的StringBuilder,将构造字符串与字符串的表示分离开来

代理模式

在不修改类的情况下,扩展一个类的功能。有静态代理和动态代理。例如JDK的动态代理,Proxy、InvocationHandler
优点:符合开闭原则
在项目中的应用:使用SpringAOP对controller的所有方法增加日志。

适配器模式

可以将一个对象适配成另一个对象,或者兼容处理不同的对象。
例如Spring AOP中使用适配器将Adivce对象适配成MethodInterceptor对象
SpringMVC中HandlerAdapter适配各种不同的Controller,由HandlerAdapter适配调用Controller的方法。

桥接模式

两个不同维度的东西组合在一起,如品牌有苹果、华为、小米,计算机有笔记本、手机、ipad,若两两作为一个类则会生成很多类,将品牌聚合到计算机这不会。例如JDK中的logging包中的Handler将日志写到不同的位置,如文件、数据库,由不同的Handler实现类做到。Formatter用于对日志进行格式化,有不同的Formatter实现类。将Formatter聚合到Handler中。

装饰器模式

在不修改类的情况下,对类进行扩展。例如FileInputStream、BufferedInputStream。BufferedInputSteam聚合了FileInputSteam,对FileInputSteam增加缓冲的功能。

外观模式

子系统过于复杂,不便于用户调用,将子系统封装成一个类方便用户调用。例如JDK的logging包,里面有子系统Handler、Formatter,我们一般只会使用统一接口Logger。

享元模式

程序可能要创建大量某个类的实例,我们通过共享技术对部分实例进行复用,减少创建。例如JVM中字符串常量池,String.valueOf返回字符串常量池中的引用。例如线程池,对线程进行复用,减少创建。

组合模式

一个统一的Component类,叶子类继承Component,容器类继承Component,且容器类聚合了Component。我们可以统一操作Component,不管他是叶子还是容器。容器可以包含叶子和容器,达到了递归的效果。例如java.awt包,Container继承Component,且聚合了Component。Checkbox继承Component,是叶子。

模板方法

一个业务有固定的步骤,但每个步骤可能对不同情况有不同实现,我们定义钩子方法,来完成固定的顺序,让不同的子类重写钩子方法,来处理不同情况。
例如Spring的JdbcTemplate,execute方法中实现了访问数据库的固定操作,如获取数据库连接、释放连接,通过回调对象来执行不同的逻辑。query、insert等方法,调用execute方法,只需传入回调对象来完成特定操作即可。

策略模式

将可供选择的不同算法封装起来作为不同的类,根据情况选择不同的类。例如Collections的sort方法传入Comparator对象来执行不同的比较算法。我们可以根据情况自定义Comparator实现类来选择合适的比较算法。

命令模式

将请求封装成命令,将发送命令和执行命令的责任分开,用户只需发送命令,不用管执行者如何执行。例如Runnable、Thread,Runnable是抽象命令,Thread是命令的执行者,我们传入Runable的实现类,就是发送具体的命令。

责任链模式

请求由一个责任链处理,责任链上有多个处理器像链表一样相连,请求不清楚具体是链上的哪些处理器处理了。例如javax.servlet包下的FilterChain、Filter。FilterChain是一条责任链,有一个数组保存多个处理器构成一条链,FilterChain的doFilter方法会调用链上的Filter的doFilter方法。

例如,红包过期、订单未支付超时过期。我们将他们存入redis并设置过期时间,过期时间到程序就进行处理,我们使用责任链模式,一个数组上有红包、订单的处理器两个构成责任链,遍历数组进行处理。

状态模式

一个对象有不同的状态,在不同状态的逻辑行为不同,我们可以通过状态模式来减少if、else。
不过我个人还是更喜欢if、else,因为使用状态模式,状态多的话类很多,状态间的转换不如if、else清晰。

观察者模式

用于一个对象状态变化时通知多个其他对象。也叫发布/订阅模式。例如JDK自带的Observable,addObserver添加观察者,创一个类继承Observable,当某个对象状态变化时,调用setChanged表明变化了,再调用notifyObservers通知观察者状态变了。

项目中的应用:
用户注册完成后,要发送邮件、发送优惠劵等。
邮件服务、优惠劵服务都订阅注册成功主题,当用户注册成功后,我们发布一个注册成功事件就可以了。

中介者模式

多个对象之间有直接交互,交互复杂,引入一个中介者,有中介者协调多个对象的交互。例如JDK中的Timer的队列中存放Task对象,由TimerThread和TaskQueue协调多个task的运行时机。

迭代器模式

将数据结构和遍历方法隔离开了。例如JDK中的Iterator接口,ArrayList的有个内部类实现了Iterator接口来实现遍历逻辑。

访问者模式

数据结构与数据结构的操作隔离开来。

备忘录模式

一个对象能创建一个记录自己当前状态的对象,在必要时可以用这个快照回到之前的状态。

解释器模式

定义一个文法,给出文法的分析程序,从而对传入的数据进行解析。JDK中的Pattern。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值