北京的冬天太干燥了,于是买了个加湿器,如下图:
此加湿器设计得还是比较有创意的,跟一般的加湿器不同,它只有主体,没有装水的地方。要加水的话,需要外接一个装水的瓶,而这种瓶子就是我们平时喝水用的饮料瓶,所以使用起来十分地方便。我们可以随时随地用一个矿泉水瓶接上去就能产生水雾,而且可以随便地更换瓶子,比如像这样:
恩。。。虽然瓶子确实有点大,不过目前它的情绪还算稳定。。。其实,这样的一个加湿器,还是蕴涵了一些程序设计的道理滴,至少包含了数据与逻辑分离、单一职责原则、针对接口编程和适配器模式;
数据与逻辑分离
这里的数据就是水(不是瓶子哦),数据是不包含在加湿器里的,它装在加湿器之外的瓶子里。如果我们想要换一种水,比如不是一般的自来水,而是带香味的或带颜色的混合液体,那我们就只需要把瓶子里的水换成想要的,然后再把瓶接上去,按下开关即可。而且此过程中,我们不需要改动加湿器的内部就可完成,如果换个水还需要把加湿器拆开,然后,找到可以加水的地方,再把水倒进去,最后再把盖子合上,拧紧螺丝。。。。。这得多麻烦啊!!也就是说,我们在代码逻辑中,不要涉及具体的数据,因为数据是会经常改变的,如果改个数据还需要先到某个类中,查找/替换的话,那这个设计就有问题了,就应该抽象出来,比如像文案、模板这些东西。
单一职责原则(SRP)
单一职责原则的意思就是说一个类最好就只做一件事,而且引起其变化的原因只有一个。如果一个类承担了多个职责,那么引起它变化的原因也会有多个。这里瓶子只需要负责装水,然后通过注水口向加湿器提供水,只有换水才能引起它的变化;加湿器主体,加湿器主体负责接收瓶子里的水,至于是什么水,它不关心,它只负责将水转换为雾气而已;电源,电源适配器为加湿器提供电源,加湿器本身并不需要存储电能,靠电源输入口接入电源即可。
ok,现在这三个功能块的职责都化分开了,如果这时加湿器不工作了,我们可以查看是没水了,还是没电了,还是雾化器不工作了。如果是没水了,我们只需要往瓶子里加上水,再接回加湿器的注水口,这里不需要对加湿器主体进行任何改动;如果是没电了,我们可以插上电源,或是换个电源,再插入加湿器,这里也不需要改动加湿器主体;如果是雾化器不工作了,那么这个加湿器的核心可能挂掉了,最快的解决方法就是换个加湿器主体,然后再接上水瓶,接上电源就能继续使用了。
由此三者的职责为: 水瓶装水,为加湿器提供水源;
电源通电,为加湿器提供电能;
加湿器主体把电能转换为动能从而把水雾化,其中,水和电是外部功能提供的,它只负责转换而已,不关心怎么来的。
然后把三者组合起来,就成了一个完整的加湿器。如果职责没有化分开,把三者整合在一起(现在有加湿器是这样做的)。这就好比设计了一个大的类,把水的处理、电的处理、雾化的处理全实现了,如果要修改其中一个功能,都需要动到这个类,而且还可能导致代码量过多。如果把这三个功能抽象成三个类,那么开发和维护相对都会容易一些,我们只需要修改我们想改的功能,比如水的处理,我就不会去修改电的处理类和雾化的处理类。如果把三个功能的信息量设为100的话,也许水的处理是30,电的处理是30,雾化的处理是40,那么30或40的信息量肯定要比100的信息量处理起来要容易一些,这也是为什么大家都提倡各功能块代码量要小的一个原因。
针对接口编程
针对接口编程,就是不要针对实现编程(废话。。。。)。。呃。。简单地说,我们要把功能做灵活。比如这个加湿器的瓶子,我可以用小瓶子(图一),也可以用大瓶子(图二),也可以用各种各样能齐形怪状的瓶子。但是,有一个不能变,那就是瓶口,因为我们需要把加湿器提供的瓶口连接器拧上去,然后再扣到加湿器上,这个瓶口连接器内有螺旋凸槽,跟一般矿泉水瓶的盖子是一样的,所以可以跟瓶子紧密结合(下图为瓶口连接器)。
这里的瓶口标准就是接口,只有符合了这个标准,才能被瓶口连接器所使用。这样做的好处就是我可以随便换瓶子,而且只关心这个瓶子的瓶口是不是符合瓶口连接器需要的标准的,不用关心瓶子长什么样。长什么样是瓶子自己的事,与瓶口连接器或加湿器主体无关,所以瓶子可大、可小、可圆、可方,只要瓶口符合标准就行,这样就满足了不同的需求。如果我们把瓶子直接做到了加湿器上面,无法分离,那么也就无法更换,也就无法满足不同的需求。这里不同的瓶子其实就是不同的类,瓶子的瓶口标准(规定了直径多大、螺旋凸槽多深等约束)就是接口(注意是瓶口标准,不是瓶口,瓶口只是该接口的实现)。如果我们把瓶子的实现写在了加湿器类里,那么我们更换瓶子的时候,就需要改动加湿器类,更换频繁的话,改动也频繁,相当地不方便,增加了维护成本。现在把瓶子的实现抽象出去,加湿器类里不关心瓶子的实现了,只关心提供一个瓶口连接器,然后去连接瓶子就行了,要更换瓶子的话也不需要修改加湿器,把旧瓶子从接口拿开,再换个实现了这个接口的瓶子,一样可以正常工作,这样后期维护起来就方便多了。。现有的设计中比如像数据的获取(sql/access/xml/json)、交互效果的呈现(一般呈现、透明度渐隐/渐显呈现)等,都是可以利用接口来达到灵活切换的目的。
适配器模式
所谓的适配器模式大概的意思就是“将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作”。现在看看这个瓶口连接器,丫就是一个适配器,它把瓶子的瓶口和加湿器的注水口连接在了一起,因为瓶口是无法直接连接在加湿器上的,所以得转换一次。瓶口连接器就是一个新的类,使用瓶口连接器来连接瓶子与加湿器的这种方式就是适配器模式。。。。顺便说一句,其实设计模式并不是什么太高深神秘的东西,它可以说是一种经验的积累,我们可能有意无意中用到它,主要是出于让代码易维护及功能扩展方便的目的,我们不用去刻意地“学习“它,而是要去”体会“它,”感觉“它。
说实话,一些道理容易懂,但要描述出来还真是挺费劲的,以上思想仅作参考。。。HOHO~~