秒懂设计模式txt电子书

简介: 本书以轻松幽默的文风,浅显易懂的方式全面地对23种设计模式进行了归纳和讲解。

第1章

初探

1.1

封装

想要理解封装,我们可以先观察一下现实世界中的事物,比如胶囊对于各类混合药物的封装;钱包对于现金、身份证及银行卡的封装;计算机主机机箱对于主板、CPU及内存等配件的封装等。

由此可见,封装在我们生活中随处可见。我们举一个现实生活中常见的例子。如图1-1所示,注意餐盘中的可乐杯,其中的饮料是被装在杯子里面的,杯子的最上面封上盖子,只留有一个孔用于插吸管,这其实就是封装。封装隐藏了杯子内部的饮料,也许还会有冰块,而对于杯子外部来说只留有一个“接口”用于访问。这样的做法是否多此一举?又会带来什么好处呢?首先是方便、快捷,只有这样我们才能拿着饮料杯四处行走,随吸随饮,而不至于把饮料洒得到处都是,因为零散的数据缺乏集中管理,难以引用、读取。其次是封装后的可乐更加干净、卫生,可以防止外部的灰尘落入,杯子里面以关键字“privat-e”声明的可乐会成为内部的私有化对象,因此能防止外部随意访问,避免造成数据污染。最后,对外暴露的吸管接口带来了极大便利,顾客在喝可乐时根本不需要关心杯子的内部对象和工作机制,如杯子中的冰块如何让可乐降温、杯体内部的气压如何变化、气压差又是如何导致可乐流出等实现细节对顾客完全是不可见的,留给顾客的操作其实非常简单,只需调用“吸”这个公有方法就可以喝到冰爽的可乐了。

图1-1 饮料的封装

我们再来分析一下对计算机主机的封装,它必然需要一个机箱把各种配件封装进去,如主板、CPU、内存、显卡、硬盘等。一方面,机箱起到保护作用,防止异物(如老鼠、昆虫等)进入内部而破坏电路;另一方面,机箱也不是完全封闭的,它一定对外预留有一些访问接口,如开机按钮、USB接口等,这样用户才能够使用计算机,计算机主机的类结构如图1-2所示。

图1-2 计算机主机的类结构

封装的概念在历史发展中也非常多见,其实它就是随着时间的推移对前人经验和技术产物的逐渐堆叠和组合的结果。举个例子,早期的枪设计得非常简陋,打一发子弹需要很长时间去准备,装填时要先把火药倒入枪管内,然后装入铅弹,最后用棍子戳实后才能发射;而下一次发射还要再重复这一过程,耗时费力。为了解决这个问题,人们开始了思考,既然弹药装填如此困难,那么不如把弹头和火药组合后封装在弹壳里。这样只要撞击弹壳底部,弹头就会被爆炸的火药崩出去,装入枪膛的子弹便可发出,如图1-3所示。

从弹药到子弹的发展其实就是对弹药的“封装”,因此大大提高了装弹效率。其实一次装一发子弹还是不够高效,如果再进一步,在子弹外再封装一层弹夹的话则会更显著地提升效率。我们可以定义一个数据结构“栈”来模拟这个弹夹,保证最早压入(push)的子弹最后弹出(pop),这就是栈结构“先进后出,后进先出”的特点。如此一来,子弹打完后只需更换弹夹就可以了。至此,封装的层层堆叠又上了一个层次,在机枪被发明出来之后冷兵器时代就彻底结束了。

图1-3 弹药的发展

在Java编程语言中,一对大括号“{}”就是类的外壳、边界,它能很好地把类的各种属性及行为包裹起来,将它们封装在类内部并固化成一个整体。封装好的类如同一个黑匣子,外部无法看到内部的构造及运转机制,而只能访问其暴露出来的属性或方法。需要注意的是,我们千万不要过度设计、过度封装,更不要东拉西扯、乱攀亲戚,比如把台灯、轮子、茶杯等物品封装在一起,或者在计算机主机里封装一个算盘。如果把一些不相干的对象硬生生封装在一起,就会使代码变得莫名其妙,难于维护与管理,所谓“物极必反,过犹不及”,所以封装一定要适度。

1.2

继承

继承是非常重要的面向对象特性,如果没有它,代码量会变得非常庞大且难以维护、修改。继承可以使父类的属性和方法延续到子类中,这样子类就不需要重复定义,并且子类可以通过重写来修改继承而来的方法实现,或者通过追加达到属性与功能扩展的目的。从某种意义上讲,如果说类是对象的模板,那么父类(或超类)则可以被看作模板的模板。

版权:人民邮电出版社