《Head First 设计模式》读后感

这是一本连目录都很有趣的书。
作者以四人帮(Gof)的《Design Patterns: Elements of Reusable Object-Oriented Software》为基础,妙趣横生、深入浅出的介绍了相关的设计模式。
软件开发有两大难点:
1、复杂度:因为软件模拟整个现实的世界,而现实世界是复杂的、无序的;
2、变化:变化是唯一不变的真理。
所以软件管理就是管理软件的复杂度和变化。设计模式让我们从以往的代码重用,上升到经验的重用,让我们的思考架构提升到模式的层面,而不是仅仅停留在琐碎的对象上。
建立一种弹性的、可维护的、可以应对变化的软件,其核心原则就是“封装变化”,封装对象的创建、方法的调用、复杂的接口等等。
封装变化就是要把变的和不变的部分分开,概括来说有三点:
1、找出变化的部分;
2、分离变化的部分;
3、封装变化的部分。

以下是根据本书整理了的一些知识点。

说明:以下的类图摘录自:rc008-designpatterns_online.pdf文件

设计模式1:策略模式(Strategy Pattern)

定义了算法族,分别封装起来,让它们之间可以互相替换,模式让算法的变化独立于使用算法的客户。

  • 设计原则1:封装变化
    找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
    其实就是封装的概念,让系统变得更有弹性。
  • 设计原则2:针对接口编程,而不是针对实现编程;
    其实就是通过多态的方式,在执行的时候改变相关的函数绑定。把经常变化的行为(可以视同是一种算法)单独封装成接口类,通过set方法,而已在执行的时候改变对应的行为。
  • 设计原则3:多用组合,少用继承;
    同设计原则2,也是针对接口进行编程,然后母类组合了这些行为类(算法),在运行的时候动态的改变行为,提高了系统的弹性。

设计模式2:观察者模式(Observer Pattern)

定了了对象之间的一对多的依赖,这样依赖,当一个对象改变状态的时候,它的所有依赖者都会收到通知并自动更新。

类似出版社+订阅者的关系,其中包括了了Subject与Observer接口的类。
观察者模式支持推(Push)和拉(Pull)的模式!
观察者模式的代表MVC。

  • 设计原则4:为了交互对象之间的松耦合设计而努力。

设计模式3:装饰者模式(Decorator Pattern)

动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

装饰者和被装饰者必须是一样的类型,利用继承达到“类型匹配”。

  • 设计原则5: 类应该对扩展开放,对修改关闭。

设计模式4:工厂模式(Factory Pattern)

工厂方法模式(Factory Method Pattern)

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法把实例化推迟到了子类。

抽象工厂模式(Abstract Factory)

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

工厂模式能将对象的创建封装起来,是应用程序解耦,并降低其对特定实现的依赖。
在子类中实例化,就可以横向扩展子类而不需要修改超类以及对超类调用的代码。
工厂方法将生产知识封装锦各个创建者,这样的做法也可以被视为是一个框架。框架的概念就是搭好框架之后,直接在里面加内容(产品)就可以了。
如果代码是针对接口而写,那么通过多态,它可以与任何新类实现该接口。

  • 设计原则6: 要依赖抽象,不要依赖具体类。

设计模式5:单件模式(Singleton Pattern)

确保一个类只有一个实例,并提供一个全局访问点。

实现单件模式,需要私有的构造器、一个静态方法和一个静态变量。
可以采用延迟实例化的方式创建单件,同时,需要考虑解决多线程的问题,例如可以通过同步synchronized来处理方法。

设计模式6:命令模式(Command Pattern)

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

命令对象包括:特定的接受者+一组动作(excute()方法)
调用者包括:持有一个命令对象+setCommand()方法+调用执行的方法
命令模式将发出请求你的对象和执行请求的对象解耦。
调用者可以接受命令当做参数,甚至在运行时动态地进行。

设计模式7:适配器模式(Adapter Pattern) 和 外观模式(Facade Pattern)

适配器模式是将一个类的接口,转换成客户期望的另一个接口。适配器让原本不兼容的类可以合作无间。

外观模式是是提供了一个统一的接口,用来访问子系统中的一群接口。外观定了一个高层接口,让子系统更容易使用。

  • 适配器将一个对象包装起来以改变其接口;
  • 装饰者将一个对象包装起来以增加新的行为和责任;
  • 外观将一群对象“包装”起来以简化其接口
  • 设计原则7:最少知识原则(Least Knowledge):只和你的密友谈话。
    只使用和本类直接相关的对象的方法。

设计模式8:模板方法模式(Template method Pattern)

在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

Hook(钩子)我们将“默认不做事的方法”称为钩子。类似,实际中的钩子,需要的时候就挂上,不需要的就放着不做事。钩子可以作为条件控制,影响抽象类中的算法流程。如果在在子类中,这个算法是可选的,就使用钩子。子类可以选择是否哦实现这个钩子方法。
模板方法模式和适合创建框架。固化算法结构(把方法申明为final),具体的某些步骤实现由子类动态处理。
模板方法的抽象类可以定义具体的方法、抽象方法和钩子。
工厂方法是模板方法的一种特殊版本。

  • 设计原则8:好莱坞原则(Hollywood Principle)
    别调用(打电话给)我们,我们会调用(打电话给)你。
    由超类主控一切,当他们需要的时候,自然会去调用子类,这就跟好莱坞一样。

设计模式9:状态模式(State Pattern)

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

这个模式将状态封装成独立的类,并将动作委托到代表当前状态的对象,我们知道行为会随着内部状态而改变。
工作步骤:1、判断当前状态;2、执行对应状态的动作;3、动作之后对应的状态(可能变、也可能不变);循环以上3步。

  • 策略模式:可以通过组合不同的对象来改变行为;
  • 状态模式:通过状态的改变来委托给不同的状态类来执行不同的行为;

和程序状态机(PSM)不同,状态模式用类代表状态。

  • 设计原则9:类应该只有一个改变的理由。

设计模式10:代理模式(Proxy Pattern)

为另一个对象提供一个替身或者占位符以访问这个对象。

包括:

  • 远程代理:控制访问远程对象;
  • 虚拟代理:控制访问创建开销大的资源;
  • 保护代理:基于权限控制对资源的访问,动态代理,是运行时才将Proxy类创建出来。

装饰者模式为对象加上行为,而代理则是控制访问。

设计模式11:复合模式(Compound Pattern)

复合模式是结合两个或以上的模式,组成给一个解决方案,解决一再发生的一般性问题。
MVC(Model-View-Controller)
Model 2:Web开发人员也都在适配MVC,使它复合浏览器/服务器模型,并使用Servlet和JSP技术的结合,来达到MVC的分离效果。

文章摘录

  • 当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
  • 改变主题或者观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只要它们之间的接口仍被遵守,我们就可以自由地改变它们。
  • 不管是在什么时候,只要我们有一大堆东西,很自然地就会想到要为他们分类,这可以帮助我们在更抽象的层次上思考这些东西。例如汽车的分类就是这样。
  • 其它书本的截图