共计 4490 个字符,预计需要花费 12 分钟才能阅读完成。
尽管你感觉大炮必定是个题目党,但你究竟还是点进来了(别打我,手动狗头保命),毕竟这性价比也太高了,4 分钟 10 种,如果是真的就赚大发了。
然而大炮能够必定的通知你,只有正儿八经的参加过几个我的项目,有个一两年的开发教训。你必定曾经用过并且可能曾经了解了一些设计模式了,只是并不自知而已。明天大炮就来给你好好缕一缕。
单例、工厂模式
这两个设计模式大家都不生疏,很多读者也都曾经自学过了。比方饿汉、懒汉单例模式,简略、形象工厂模式。而且这两个模式,就像兄弟一样,常常结对呈现。所以大炮放到一起来讲,咱们先来看一行代码:
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
十分眼生吧,这是咱们平时用来获取日志对象的一段代码,然而重点并不是这个 logger 而是 LoggerFactory,顾名思义用来 专门用来造 logger 的 工厂,是一个工厂模式很好的体现。同时作为工厂呢,它又是单例的,毕竟 new 一个工厂就够了嘛,本人实例化那么多个干嘛呢,单例杜绝了重复创立和销毁对象的开销。
同时它又用到了门面模式,这行代码是不是很牛,用到了三个设计模式,咱们接着往下看。
门面模式
在《阿里巴巴 Java 开发手册》中,对于日志章节中专门有提到:
【强制】利用中不可间接应用日志零碎 (Log4j、Logback) 中的 API,而应依赖应用日志框架 SLF4J 中的 API,应用门面模式的日志框架,有利于保护和各个类的日志解决形式对立。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
有点感觉没,门面模式其实就是把本人作为一个接口,本人并不提供真正的实现。什么,还是没到位?那咱们看看上面这段代码:
是不是又很眼生了,下单要干挺多事件,保留订单,保留订单项,减库存 … 或者还有其余业务,如果所有这些办法的实现都放到 createOrder 这个办法外面,那代码必定是又长又臭,洋洋洒洒就奔着几百上千行去了。所以有教训的你们必定会抽到好几个子办法外面,就像下面一样,而后挨个调用下就行了。(PS,真正的下单代码必定不是这么玩的,高并发下必定挂了,看个意思就好)
没错,这也是门面模式,createOrder 办法并没有给出具体的实现,间接调用了几个子办法而已。可能有些读者心里曾经收回了讥嘲:就这?就这?这也算设计模式?我本人都会写啦。
没错,就这~设计模式就是对教训的总结,而后提出了一些倡议和标准。其实并不是如许浅近的货色。当初想想,如果给优良的咱们早生几年,有些设计模式的创造者还指不定是谁呢。回到下面的代码,尽管没多少技术含量,但对调用者而言,我 管你怎么实现,我微微调一下 createOrder 办法就完事 了。这正是门面模式的精华所在。
嗯,一行代码 get 到了三个设计模式。咱们持续。
代理模式
代理模式,是一个十分重要的设计模式,不了解它可能会让你间接无缘大厂。大家肯定要学会并了解这个货色。咱们先来看一段代码:
How old are you ? 怎么老是你 ? 没错,还是下面的图。这次的关注点大家放在 @Transaction 上。注解自身没啥用,只是作为一个标记,有时候会携带一些配置信息。老开发曾经晓得我要讲啥了,这里用到了 Spring 中一个十分的重要个性:AOP 编程。而 AOP 的实现原理就是代理模式。
代理模式的作用就是职责(或者说性能)加强。那 Spring 帮咱们做了哪些加强呢?上图的局部其实只有 CRUD 的业务代码,事务方面一行都没有。而没 Spring 之前,咱们是要这样写的:
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 建设连贯
Connection con = DriverManager.getConnection()
// 开启事务
con.setAutoCommit(true/false);
// 真正的、咱们每天都要写的:)
C R U D
// 提交事务
con.commit()} catch (Exception e){
// 失败了还要本人手动回滚
con.rollback();} finally {
// 敞开连贯
conn.close();}
写的伪代码,不必在意细节。重要的是如果每个须要用到事务的办法都要这么反复写,咱们预计早疯了。这里 Spring 就将这些反复的代码应用动静代理给咱们抽到代理类中去了,所以咱们只用关注 CRUD 就成——从这个角度看,肯定水平上造成了程序员的懈怠,不是咱们不学习,只怪 Spring 太好用。
代理模式就不持续发散了,前面会精讲。
桥接模式
让我猜猜看,是不是有些同学第一次听到这个模式?猜对了待会上面给我留言点赞统计喔,但其实,咱们每天都在用。咱们来看一段代码:
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 建设连贯
Connection con = DriverManager.getConnection()
没错,大炮又套娃了,用的就是下面的连贯数据库的代码。大家每天都要连贯数据库的吧。
先铺垫一个常识:Java 没有真正能操作数据库的办法,只是提供了一些形象的接口,真正的实现在各个数据库厂商提供的相应 jar 包内。mysql 就由 mysql 的开发者提供,oracle 的就由 oracle 的提供。
为什么咱们这个 DriverManager 能间接 get 到 Connection 呢,就是应用了桥接模式。要害就在于这个 Class.forName(“com.mysql.jdbc.Driver”),Class.forName 只是加载了一个类而已,怎么做到的呢。咱们来看这个 Driver 类到底干啥了:
其实就是一个动态块外面调用了java.sql.DriverManager 的 registeDriver 办法,而后把mysql 的 Driver 对象传了过来,起到了一个搭桥的作用。
多的就不扩大了,桥接模式的作用就是连贯了一个形象维度和一个实现维度。这里的形象维度就是指 java,实现维度就是指 mysql。其实也能够说桥接的精华在于“约定”,java 和 各数据库厂商约定:你们底层实现我不论,然而你们得依照我的规矩来,调用我 DriverManager 的 registerDriver 办法才行。
中介者模式
聊完桥接模式,不得不聊下中介者模式了。桥接是关注两个维度的连贯,而中介者是关注多个多个维度。作用是 对立治理多个多个维度的网状资源 。没错,可能你曾经想到了,咱们天天都在用的 注册核心就是一个中介者,比方 eureka、zookeeper。
如图,所有的 service 都只和 Service Registry 耦合,而不是间接去依赖其余 service,中介者完满地解决了网状依赖的简单关系带来的代码凌乱。总体来说中介者还是个比拟容易了解的设计模式,这里就不做太多开展了。
解释器模式
解释器模式是个非常简单的模式,有种自娱自乐的滋味,如果你晓得它是怎么自娱自乐的,那你也能跟着“娱乐一下”。来看一个相熟的东东:
# 每隔五秒执行一次 times = */5 * * * * ?
你的配置文件是不是也有 corn 表达式呢,这就是一个解释器模式的体现。可能当初你的心田又:
解释器模式定义了一种表达式(或者说是语言),并且也提供了解析表达式(语言)的办法。相似的还有正则表达式。Spring 中的 ExpressionParser 也用到了解释器模式,有趣味的同学能够去看看源码。
策略模式
策略模式也比拟容易了解,大家在开发和日常生活中也常常用到,也是一个须要重点把握的设计模式。每天买货色,应用手机领取,就是策略模式的一种体现。策略模式只重视后果,不论应用哪种策略(策略模式要求策略的数量是无限的),最初的后果都是一样的。比方手机领取,不论应用哪种领取形式,该付多少还是得付多少。
原型模式
原型模式也是一种非常简单,唉,凌晨一点多了。今天持续写吧。困了困了。
诶大炮又复活了。原型模式也是一种非常简单的设计模式:给定一个对象实例,通过拷贝的技术创立新的对象,达到对象复用的成果。来看一段代码:
UserVo userVO = new UserVO();User user = mapper.selectByPrimaryKey(id);if(user == null){throw new Exception("未获取到指定用户");}/* 拷贝数据,传给前端大佬渲染页面 */BeanUtils.copyProperties(user,userVO);return userVO;
是不是十分眼生了,可能有些读者心田纷纷表示“是我自己没错了”。这里的 BeanUtils.copyProperties 办法就用到了原型模式外面的 浅拷贝。
略微提一句,不要应用 Apache 的 BeanUtils 来 copy。性能问题比较严重,在《阿里巴巴 Java 开发手册》中也有专门提到。如果须要切到 Spring 的 copy 办法,也有个坑须要留神下,这两家的提供的 copy,类名雷同、办法名也雷同。但 参数的地位相同,切换时请多加留神并做好测试。
迭代器模式
迭代器模式大家也天天都在用,间接上代码:
这是一段生成签名时,拼接参数的算法。外面的 Iterator 就是迭代器模式的体现,给汇合提供了一个全局拜访点,通过 hasNext()判断没有下一个节点,next()办法获取下个节点,直到所有节点都被拜访过。咱们罕用的 HashMap,ArrayList 顶层都是 Collection,而 Collection 又继承了 Iterator 接口。来张 ArrayList 的类图感触下:
小结
大炮略微给大家缕了一遍,有些同学是不是感觉本人又行了,原来人不知; 鬼不觉间,本人居然用了这么多设计模式,却不自知。其实还有很多,比方:
- 责任链模式,Spring security、Shiro 这些权限框架都有用到。
- 观察者模式,Spring 的 ContextLoaderListener 就有用到。
- 模板模式,Spring 中的 JdbcTemplate 有用到。
设计模式无处不在,平时开发咱们也无时无刻在享受着设计模式带来的益处,只是有些同学不足一个零碎的认知。因为篇幅起因就不再过多介绍了。
好吧,题目党不算太过分,超了三分钟嘻嘻。
下期预报
明天讲的还是比拟全面和粗暴的,很多细节都没有体现进去。这一期相当于是个设计模式的面试尝鲜版,下一期会对设计模式做一个正式的介绍:
- 为什么要用设计模式
- 设计模式是什么
- 设计模式有哪些
- 设计模式的分类
大略就是下面这些了。而后就开始做具体某个模式的详细分析和代码实现(想先看什么模式记得私信我喔)。
明天就先到这了,下次去面试被问到用过哪些设计模式,心里是不是就有底了,间接给他一顿连招 13 种通通安顿上。咱们下期见。
往期举荐
- 蔡大炮筹备正式倒闭了
- 家雄又写 bug 了
微信搜寻 java-caidapao,关注大炮~ 回复“面试题”,支付 2020 最新面试题