读书笔记-《Head First 设计模式》

来源:互联网 发布:内置软件卸载 编辑:程序博客网 时间:2024/04/29 10:59

为什么要学习设计模式?在大学的系统分析设计课程上,就开始知道有20几种基本的设计模式,但一直都没有去学习过。促使我想好好学习下设计模式的一个时机,是在第一家公司的最后2年时间里,维护开发的一个项目。代码维护很困难,大量代码重复,相同的处理不同的实现细节,小功能改动,造成大量的测试case改动,copy还易出错。现有方式很难扩展,真是牵一发而动全身。印象深刻一点的是有一个功能是读取其他接口提供的CSV文件,更新到数据库。代码实现是直接按行读文件,再split成数组,有一百多个数据项,每个项目上都数据合法性检验,还有很复杂的相关项check,最后拿数据值去更新数据库。有次需求变更,CSV文件定义修改了三分之一的字段,包括增加、删除;算上项目位置顺序变化,因为用的是数组,100多个数据项的数组下标都变了,全部的数据都要重新测试,由于数据业务组合很多,代码重写和测试的量都特别大。如果把这个功能完全重构,所有其他调用这个功能,但是这次没有业务改动的,也需要重新测试。上线时间紧,最后只能按原来的方式修改,很痛苦。后来有一次机会,新开发一个类似功能,由于有足够的时间,采用配置文件的做法,把各个项目的位置、在数据库中对应的字段、所有check类型都定义好。这个定义配置文件加载一次后就缓存下来,之后的实现就优雅多了,check可以迭代去做,DAO可以通过配置文件去对应获取数据,代码大量减少,可读性也高,原数据文件改动,UT不再需要修改,只需要改配置文件即可,以后相似的功能可以慢慢替换过来。

吃过苦头后,才更深刻地明白,填坑不如少挖坑。

扯远了,回到主题,《Head First设计模式(Design Pattern)》这本书看起来很厚,其实读起来特别快,深入浅出,也很有趣味,内容组织方式别具风格。每个章前都有一个现实的故事需求,后有对话内容也非常棒。看完这本后觉得Head First系列的应该都会不错。当初选择这本书,另一个原因就是它里面所有的示例都是Java的,自己做的也是Java。

个人觉得学习设计模式,并不是要记住定义,要多理解,了解它是什么场景下产生的,解决的是哪一类问题,如果下次自己遇到类似的问题,就会有印象,可以回过头来翻翻UML类图。其次就是要深入领会OO设计原则,为了好扩展,便于维护,模块内高聚合,模块间低耦合。知道这样做的利弊,遇到问题时才能权衡得失,没有绝对的好。再就是熟悉各模式的UML类图,了解设计模式后,在看别人的代码时,才会突然发现结构似曾相识,有时候看完一部分很自然就觉得还应该有其他部分的类,有时候class很多,没有必要每一个都去细看。之前看到过的,觉得很别扭的代码,现在觉得合理了,举例刚学Java时,觉得IO怎么老是包了一层又一层,实现的又都是同一个接口,很费解,知道装饰者模式后,一切都那么自然了。还有一个好处就是专业词汇,方便交流。设计模式还有一些变体,思想才是最重要的,多看多实践。记住简单原则,不要滥用设计模式。

关于设计模式和效率问题,因为设计模式的引入,发现会多生成很多类,运行时会多生成很多对象,直接的调用变成了几层,会不会对性能造成影响。个人经验是,好的结构能带来更多地好处,关于项目实施,我们首要考虑的是其功能正确性,好的结构,好的可读性,然后才是在写代码时要有性能意识,少生成对象,少进行循环。真正遇到性能问题时,一个好的代码结构,更容易改善,还有改性能时不能凭感觉,一定要有测试数据对比。关于改善性能的两个原则:第一不要改善性能;第二记住第一条。

另外关于设计模式的经典就是四人帮的设计模式,。下面是看书过程中的一些摘要,手打了一遍

一.策略模式(Strategy Pattern)

设计原则:
1.找出应用中可能需要变化之处,把它们独立出来(封装),不要和那些不需要变化的代码混在一起。
2.针对接口编程(针对超类型supertype编程),而不是针对实现编程。可以更通俗地理解为“变量声明类型应该为超类型”
3.多用组合(composition),少用继承。使用组合建立系统具有很大的弹性,不仅可以将算法簇封装成类,更可以“在运行时动态改变行为”
策略模式定义了算法簇,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

二.观察者模式(Observer Pattern)

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。(出版者+订阅者=观察者模式)
设计原则:
4.为交互对象之间的松耦合设计而努力。(loose coupling)

三.装饰者模式(Decorator Pattern)

5.类应该对扩展开放,对修改封闭。
装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
Java I/O库是装饰者模式的实例

四.工厂模式(Factory Pattern)

工厂方法模式定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
6.要依赖抽象,不要依赖具体类。(遵循依赖倒置原则:变量不可以持有具体类的引用;不要让类派生自具体类;不要覆盖基类中已实现的方法。)
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

五.单件模式(Singleton Pattern)

单件模式确保一个类只有一个实例,并提供一个全局访问点。
多线程环境下可用双重检查加锁(DCL在多线程下不能正确工作)、急需实例化、方法同步的方法,另外保证是同一个类加载器来生成实例,来确保只生成一个实例

六.命令模式(Command Pattern)

命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

七.适配器模式(Adapter Pattern)与外观模式(Facade Pattern)

适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器能让原本接口不兼容的类可以合作无间。
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
6.最少知识原则:只和你的密友谈话(减少对象之间的交互,不要让太多的类耦合在一起)。

八.模板方法模式(Template Method Pattern)

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
7.好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。(只能高层组件调用低层组件,避免环状依赖)

九.迭代器(Iterator Pattern)与组合模式(Composite Pattern)

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
8.单一责任原则:一个类应该只有一个引起变化的原因。
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

十.状态模式(State Pattern)

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。(把一个状态的所有行为放在一个类中)

十一.代理模式(Proxy Pattern)

代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。

十二.复合模式(Compound Pattern)

复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题。

十三.设计模式

模式是在某情境(Context)下,针对某问题的某种解决方案。原则:保持简单(Keep It Simple)。使用模式前要权衡得失,不要滥用模式。

附录其他模式

桥接模式(Bridge Pattern)通过将实现和抽象放在两个不同的类层次中而它们可以独立改变。
生成器模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。封装一个产品的构造过程,并允许按步骤构造。
责任链模式(Chain Of Responsibility Pattern)让一个以上的对象有机会能够处理某个请求。让请求的发送者和接受者解耦;沿着链条传递请求,直到有一个对象处理它为止。
蝇量模式(Flyweight Pattern)让某个类的一个实例能用来提供许多“虚拟实例“。
解释器模式(Interpreter Pattern)为语言创建解释器。
中介者模式(Mediator Pattern)集中相关对象之间复杂的沟通和控制方式。
备忘录模式(Memento Pattern)让对象能返回之前的状态
原型模式(Prototype Pattern)通过复制现有的实例来创建新的实例。
访问者模式(Vistor Pattern)作用于某对象结构中的各元素的操作,使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。为对象组合增加新的能力。

0 0