尽管你感觉大炮必定是个题目党,但你究竟还是点进来了(别打我,手动狗头保命),毕竟这性价比也太高了,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最新面试题