一直以来,自己读过的技术类书籍也不少了,但是都犯了一个毛病就是没有很好的记录下来,有些东西可能并不是平日开发中时时刻刻用到的,随着时间的延长,学过的东西慢慢也就淡忘了,刚好最近有些时间,也正打算把<<设计模式之禅>>这本书好好的通读一遍,顺便把所想所得详细的记录一下,也方便以后查阅和回顾。
好,以上都是“废话”,接下来切入正题。
提起这个设计模式啊,额...,还是打算再废两句话,没办法我这人就是啰嗦,当然你也可以说我是凑字数。
我这个人呢,比起看A片,平日我更喜欢看小说,而且还是玄幻爽文类的,没办法,我就是这么有个性。这类小说呢,都有一个共同的特性就是男猪脚都会修炼很吊炸天的功法,然后在修真界各种装逼各种秀,一般这种功法有时候初期的时候还都很平平无奇,甚至是人尽皆知,但就是没几个人练成,你说气人不。。。但偏偏男猪脚却。。。好了好了,哈哈,该打住了(任性也得有个限度不是?)咱们这里刚才提到了功法,对,设计模式给我的第一印象就像是一部逆天功法,看似平平无奇人尽皆知,可是能够大成者却少有,更别说臻至化境了,但江湖上一直有个传说便是能够将此功法练至化境的便可以打破这世界的禁锢成为天下至尊。
说了那么多,和今天的单一职责原则有什么关系呢?
要想修炼一部功法,最基本的就是要明白功法运行的轨迹、运气方法啊等等最基本的修炼方式或者说是约束规则,而设计模式之中就有那么六大基本的原则,也就是咱们修炼这部功法的基本规则,分别是单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则(当然有人也会将组合/聚合复用原则总结进去,称为设计模式的七大原则)。
而我们今天要聊的就是最简单、最基础、也最让人糊涂的-----单一职责原则。
其实从字面的意思我们也很容易理解单一职责原则,说白了就是确保你写的东西(类、接口、方法)有着单一的职责,很多时候我们都拿人(person)来举例子,我们也拿这个person来举例子,但咱们这个例子和他们的不太一样,毕竟咱们谈论的是修炼,这个人的身体结构还是要了解清楚的,不专业的讲,人有双手、双脚、一个头、五脏、六腑、、、等等对吧?这里我们的划分其实就是单一职责原则的一种表现,我们的头就是用来思考和观察的,我们的手就是来拿东西的,脚就是用来走路的,这个时候有人就说了,“老弟啊你还是太年轻,谁说手就只能来拿东西啊,老哥我练的蛤蟆功用手走路也不是问题的啊”,对,没毛病,练铁头功的那哥们用头走路都可以。这也就是我们平时开发中经常会遇到的或者经常困惑的地方,就是如何划分这个“职责”的问题,准确的说这个职责的划分,确实没有特定的界限,这要根据你自己的业务(也就是你所习功法的效果)来决定,您老修炼飞檐走壁,老拿头来走路也不是那么回事吧。
说到了这里,您可能大致的了解了这个所谓的单一职责原则,但是我们在代码中怎么写呢?或者说我们修炼的时候怎么处理呢?咱们接下来就仔细的看看吧。
修炼的阶段一般都有那么几种,比如聚气、淬体、拓脉、元婴、紫府。。。。,我们拿结元婴来举个例子,就像咱们上面提到的person,咱们也造个小人吧。
由于咱们目前功力低微,咱们元婴那小人就不要太复杂了,一个头俩胳膊俩腿就够了,咱这个小人能干嘛呢?也就只能盘腿打坐、掐口诀聚气、冥想了
说到这里,咱们就要开始思考了,我练就这个小人是干嘛的(也就是我们要处理什么业务的)目的很简单,让这小人可以在我们的气海内自行修炼运转功法,以便提升我们的修炼速度,当我们遇到致命危险的时候,可以驾驭元婴隐匿逃脱(这也就是我们要实现的功能)。
咱们这里整理出来两个主要的功能一、提升修炼速度 ,二、隐匿逃脱,来看图
根据上面这个图,咱们先理一理,我们修炼元婴的目的有两个分别是提升修炼速度和隐匿逃脱,用元婴来提升修炼速度我们需要三种方法一是掐手决、二是打坐、三是冥想,而这三种方法分别需要我们的手、脚、头去完成,同样使用元婴隐匿逃脱也有三种方法同样也需要手、脚、头去完成。
我们得出一个结论,我们无论实现什么功能,都离不开手、脚、头。
我们稍加修改再来看这个图:
可能看到这里,很多同学已经蒙了,“老弟啊,咱不是再说单一职责原则吗?刚才还挺清楚,咋越说越蒙呢?说好的代码呢?”
额,说实话,大哥其实我也蒙了,说来说起我都把握自己绕进去了,先让我缓会。。。。。。。。。。。。。。。。。。
好了,缓好了,咱们接着扯。。。
上面的两个例子呢,其实牵扯到两种方式,一是使用接口的单一职责原则,另一个是使用类的单一职责原则,
咱们先看第一个图,第一张图是以功能来划分的,也就是我们要达到的效果,这种时候我们采用的应该是接口执行单一职责原则,也就是说,您不用管我怎么提高的修炼速度,或者不用管我怎么隐匿逃脱的,我的提升修炼速度的接口就是提升修炼速度的我不管你隐匿逃脱的事,你隐匿的接口就是负责隐匿逃脱别的你也别管,(巴啦啦一大堆,还是看代码吧。。。)看代码:
/**提升修炼*/ public interface TiShengXiuLian { /** * 掐手决 * @param hand */ void qiaShouJue(Hand hand); /** * 打坐 * @param foot */ void daZuo(Foot foot); /** * 冥想 * @param head */ void mingXiang(Head head); } /**隐匿逃跑*/ public interface YinNiTaoPao { /** * 虚空隐匿 * @param hand */ void xuKongYinNi(Hand hand); /** * 飞天之术 * @param foot */ void feiTianZhiShu(Foot foot); /** * 遁地之术 * @param head */ void dunDiZhiShu(Head head); } /**元婴*/ public class Person implements TiShengXiuLian, YinNiTaoPao { private Head head = new Head(); private Hand hand = new Hand(); private Foot foot = new Foot(); @Override public void qiaShouJue(Hand hand) { //掐手决 } @Override public void daZuo(Foot foot) { //打坐 } @Override public void mingXiang(Head head) { //冥想 } @Override public void xuKongYinNi(Hand hand) { //虚空隐匿 } @Override public void feiTianZhiShu(Foot foot) { //飞天之术 } @Override public void dunDiZhiShu(Head head) { //遁地之术 } private void xiuLian() { /*掐手决*/ qiaShouJue(hand); /*打坐*/ daZuo(foot); /*冥想*/ mingXiang(head); } private void taoPao() { /*如果哪都有人*/ xuKongYinNi(hand); /*如果天上没人*/ feiTianZhiShu(foot); /*如果地下没人*/ dunDiZhiShu(head); } }
我们来分析一下上面的代码,我们的关注点是功能(修炼用来干嘛的),我们不管用什么来实现,我要的就是这种效果,我们抽取了两个接口一个是提升修炼的,一个是隐匿逃跑的,这两个接口都有着自己单一的职责,假如有一天我又新增了一个逃跑的手段,我直接修改我的逃跑接口就好了,并不耽误咱们修炼。
那好,咱们再来看第二种情况,也就是类的单一职责的代码:
/** * 头部 */ public class Head { public void mingXiang(){ System.out.println("冥想"); } public void dunDi(){ System.out.println("遁地"); } } /** * 手 */ public class Hand { public void shouJue(){ System.out.println("手决"); } public void xuKong(){ System.out.println("虚空"); } } /** * 脚 */ public class Foot { public void daZuo(){ System.out.println("打坐"); } public void feiTian(){ System.out.println("飞天"); } } /** * 元婴 */ public class Person { private Head head = new Head(); private Hand hand = new Hand(); private Foot foot = new Foot(); /** * 修炼 */ private void xiuLian() { /*头部冥想*/ head.mingXiang(); /*掐手决*/ hand.shouJue(); /*打坐*/ foot.daZuo(); } /** * 逃跑 */ private void taoPao() { /*遁地*/ head.dunDi(); /*虚空*/ hand.xuKong(); /*飞天*/ foot.feiTian(); } }
这次我们是按照身体的部位来进行的分化,我们手、脚、头都有着自己的单一职责互不影响,假如有一天咱们遇到强敌,被断去一臂,也是不会影响咱们去施展飞天之术来逃跑的,也不影响以后打坐来修行的。
好了,扯了那么多,其实单一职责原则,没那么复杂,是我想着形象点去说明情况,才搞的绕来绕去,你只要记住一点,类、接口、方法,咱们完成的功能就要单一,吃饭就是吃饭,别想着吃完还得拉,索性写一个里面,那是不对的,那种代码不光写起来恶心,吃(读)起来更恶心
总结:
其实呢,单一原则是最简单的一个原则,也是最不容易把握的一个原则,但无论你从哪个点出发,都应该记住,我就是我,是不一样的烟火,吃就是吃,想拉你就进厕所。好了,今天就扯到这里吧,来日方长,各位咱们江湖见,哈哈,对了各位有谁看见“方长”去了哪个方向???
(哈哈,小白一枚,若有不对之处,还望多多指教)