从1月15号到2月28号,我第三遍阅读完了这本《大话设计模式》,这是一本非常有意思的书。它不是一本程序集也不是一本故事集,而是一本通过故事讲述程序如何设计的方法集。书中为每一种设计模式都列举了一到多个例子,浅显易懂,引导读者体会设计演变过程中蕴藏的大智慧。特别要提出最后一章--OOTV杯超级模式大赛写的实在太过精彩,一些桥段让我止不住的拍案叫奇,佩服作者将生活场景与模式总结把控的如此之妙。用作者的一句话说就是——将编程融入生活。
本书以小菜面试受挫为故事切入点,讲述了小菜跟随大鸟一路过关斩将最终成功登上了自己的舞台。对于我们初学者来说何尝不希望有一个大鸟一般的人教导自己,不论是在技能上或是职场上,书中以常见的生活场景引入设计模式,将生活常理与编程思想相结合,阅读完后我有一种编程思想来源于日常生活,设计模式则是大师们智慧的结晶。阅读设计模式就是阅读大师们在遇到问题时所使用的解决方案。面向对象设计其实就是希望做到代码的职责分离。
无痴迷不成功:一个程序员如果从来没有熬夜写程序的经历,不能算一个好程序员,因为他没有痴迷过,所以他不会有大成就。
设计模式现在被总结出来的一共有23种,可分为三大类,分别是创建型模式它包含:抽象工厂、建造者、工厂方法、原型以及单例,第二种结构型模式它包含:适配器、桥接、组合、装饰、外观、代理。第三种行为型模式它包含:观察者、模板方法、命令、职责链、解释器、中介者、访问者、策略、备忘录、迭代器等。设计模式需要遵循一些设计原则,包含单一职责原则、开放封闭原则、依赖倒转原则、里适代换原则、迪米特法则等。下面将分别对上述内容进行介绍并带有每节事例故事标题便于记忆。
设计原则:
1、单一职责原则 --拍摄UFO--,就一个类而言,应该仅有一个引起它变化的原因。也就是说我们在设计类的时候需要做职责分离,让类的职责范围更简单更单一。
2、开放-封闭原则 --考研求职两不误--,软件实体(类、模块、函数等等)应该是可以扩展,但不可被修改。既对扩展开发而对修改封闭。在设计时需要尽可能考虑到可能发生的变化种类,然后构造抽象来隔离这些变化。
3、依赖倒转原则 --会修电脑不会修收音机--,抽象不应该依赖于细节,细节应该依赖于抽象。高层模块不应该依赖于底层模块,两者都 应该依赖于抽象。应针对接口编程而不要对于实现编程。
4、里适代换原则 --会修电脑不会修收音机--,子类型必须能够替换掉它的父类型。也就是说在软件里面,把父类替换成子类,程序的行为没有变化。此举能使父类型真正被复用,且在无需修改的情况下由子类扩展。
5、迪米特法则 --无熟人难办事-- ,如果两个类不必彼此直接通信,那么这两个类就不应发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。其根本思想是降低类之间的松耦合,类之间的耦合度越低,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。
设计模式:
1、策略模式(Strategy)--商场促销-- ,它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。策略模式定义了一系列算法的方法,从概念上来看,所有这些算法完成都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法与使用算法类之间的耦合。
2、装饰模式(Decorator)--穿什么有这么重要-- ,动态的给一个对象添加一些额外的职责,就增加功能而言,装饰模式比生成子类更加灵活。把类中的装饰功能与核心功能分离开,这样可以简化原有的类。
3、代理模式(Proxy)--为别人做嫁衣-- ,为其他对象提供一种代理以控制对这个对象的访问。此模式的应用场景有远程代理、虚拟代理以及安全代理。
4、工厂方法模式(Factory Method)--雷锋依然在人间-- ,定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工厂方法使得内部逻辑判断转移到了客户端。你想要加功能,本来是要改工厂类的,现在是要修改客户端类。
5、原形模式(Prototype)--简历复印-- ,用原形实例指定创建对象的种类,并且通过拷贝这些原形创建新的对象。原形模式分为浅复制与深复制,浅复制只复制所有的变量,而所有对其他对象的引用仍指向原来的对象,深复制会把引用对象的变量指向复制过的新对象。
6、模板方法模式(TemplateMethod)--考题抄错会做也白搭-- ,定义一个操作中的算法骨架,而将实现一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通过把不变的行为搬移到超类,去除子类中的重复代码,把变化与不变相分离。
7、外观模式(Facede)--牛市股票还会亏钱--,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。当子系统非常难以维护与扩展了可考虑增加外观类来减少新系统与老系统之间的依赖。
8、建造者模式(Builder)--好菜每回味不同--,将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。主要用于创建一些复杂对象,这些对象内部的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
9、观察者模式(Observer)--老板回来,我不知道--,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所用观察者对象,使他们能够自动更新自己。当一个对象的改变需要同时改变其他对象时,而且它不知道有多少个对象有待改变时,应该考虑使用观察者模式。
10、抽象工厂模式(Abstract Factory)--就不能不换DB吗--,提供了一个创建一系列相关或相互依赖的接口,而无需指定他们具体的类。它使得更换产品的系列更加容易(如更换数据库)。
11、状态模式(State)--无尽加班何时休--,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。当一个对象的行为取决于它的状态,并且必须在运行时刻根据状态改变他的行为时,就可以考虑使用状态模式了。
12、适配器模式(Adapter)--在NBA我需要翻译--,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于原本接口不兼容而不能一起工作的那些类可以一起工作。适配器主要应用于希望复杂一些现存但接口不匹配的类。
13、备忘录模式(Memonto)--如果再回到从前--,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。适用于需要维护或记录历史属性的类。
14、组合模式(Composite)--分公司,部门--,将对象组合成树形结构以表示部分整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。应用于需求中体现部分与整体层次结构时。
15、迭代器模式(Iterator)--想走?可以!先买票--,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。当你需要遍历一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
16、单例模式(Singleton)--有些类也需计划生育--,保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多少个对象,一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
17、桥接模式(Bridge)--手机软件何时统一--,将抽象部分和它的实现部分分离,使它们都可以独立的变化。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合。
18、命令模式(Command)--烤羊肉串引来的思考--,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如测小/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
19、职责链模式(Chain of Responsibility)--加薪非要老总批--,使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构。结构是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接收者的引用。
20、中介者模式(Mediator)--世界需要和平--,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。由于中介者对象控制了集中化,于是就把交互的复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个对象都有复杂。
21、享元模式(Flyweight)--项目多也别傻做--,运用共享技术有效地支持大量细粒度的对象。如果发现许多实例除了几个参数外基本都是相同的,那么可以考虑把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少实例的数目。
22、解释器模式(interperter)--其实你不懂老板的心--,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。如果一种特定类型的问题发生的频率足够高,那么可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
23、访问者模式(Vistor)--男人和女人-- ,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式把处理从数据结构分离出来,适用于有比较稳定的数据结构,又有易于变化的算法。
本书以小菜面试受挫为故事切入点,讲述了小菜跟随大鸟一路过关斩将最终成功登上了自己的舞台。对于我们初学者来说何尝不希望有一个大鸟一般的人教导自己,不论是在技能上或是职场上,书中以常见的生活场景引入设计模式,将生活常理与编程思想相结合,阅读完后我有一种编程思想来源于日常生活,设计模式则是大师们智慧的结晶。阅读设计模式就是阅读大师们在遇到问题时所使用的解决方案。面向对象设计其实就是希望做到代码的职责分离。
无痴迷不成功:一个程序员如果从来没有熬夜写程序的经历,不能算一个好程序员,因为他没有痴迷过,所以他不会有大成就。
设计模式现在被总结出来的一共有23种,可分为三大类,分别是创建型模式它包含:抽象工厂、建造者、工厂方法、原型以及单例,第二种结构型模式它包含:适配器、桥接、组合、装饰、外观、代理。第三种行为型模式它包含:观察者、模板方法、命令、职责链、解释器、中介者、访问者、策略、备忘录、迭代器等。设计模式需要遵循一些设计原则,包含单一职责原则、开放封闭原则、依赖倒转原则、里适代换原则、迪米特法则等。下面将分别对上述内容进行介绍并带有每节事例故事标题便于记忆。
设计原则:
1、单一职责原则 --拍摄UFO--,就一个类而言,应该仅有一个引起它变化的原因。也就是说我们在设计类的时候需要做职责分离,让类的职责范围更简单更单一。
2、开放-封闭原则 --考研求职两不误--,软件实体(类、模块、函数等等)应该是可以扩展,但不可被修改。既对扩展开发而对修改封闭。在设计时需要尽可能考虑到可能发生的变化种类,然后构造抽象来隔离这些变化。
3、依赖倒转原则 --会修电脑不会修收音机--,抽象不应该依赖于细节,细节应该依赖于抽象。高层模块不应该依赖于底层模块,两者都 应该依赖于抽象。应针对接口编程而不要对于实现编程。
4、里适代换原则 --会修电脑不会修收音机--,子类型必须能够替换掉它的父类型。也就是说在软件里面,把父类替换成子类,程序的行为没有变化。此举能使父类型真正被复用,且在无需修改的情况下由子类扩展。
5、迪米特法则 --无熟人难办事-- ,如果两个类不必彼此直接通信,那么这两个类就不应发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。其根本思想是降低类之间的松耦合,类之间的耦合度越低,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。
设计模式:
1、策略模式(Strategy)--商场促销-- ,它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。策略模式定义了一系列算法的方法,从概念上来看,所有这些算法完成都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法与使用算法类之间的耦合。
2、装饰模式(Decorator)--穿什么有这么重要-- ,动态的给一个对象添加一些额外的职责,就增加功能而言,装饰模式比生成子类更加灵活。把类中的装饰功能与核心功能分离开,这样可以简化原有的类。
3、代理模式(Proxy)--为别人做嫁衣-- ,为其他对象提供一种代理以控制对这个对象的访问。此模式的应用场景有远程代理、虚拟代理以及安全代理。
4、工厂方法模式(Factory Method)--雷锋依然在人间-- ,定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工厂方法使得内部逻辑判断转移到了客户端。你想要加功能,本来是要改工厂类的,现在是要修改客户端类。
5、原形模式(Prototype)--简历复印-- ,用原形实例指定创建对象的种类,并且通过拷贝这些原形创建新的对象。原形模式分为浅复制与深复制,浅复制只复制所有的变量,而所有对其他对象的引用仍指向原来的对象,深复制会把引用对象的变量指向复制过的新对象。
6、模板方法模式(TemplateMethod)--考题抄错会做也白搭-- ,定义一个操作中的算法骨架,而将实现一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通过把不变的行为搬移到超类,去除子类中的重复代码,把变化与不变相分离。
7、外观模式(Facede)--牛市股票还会亏钱--,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。当子系统非常难以维护与扩展了可考虑增加外观类来减少新系统与老系统之间的依赖。
8、建造者模式(Builder)--好菜每回味不同--,将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。主要用于创建一些复杂对象,这些对象内部的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
9、观察者模式(Observer)--老板回来,我不知道--,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所用观察者对象,使他们能够自动更新自己。当一个对象的改变需要同时改变其他对象时,而且它不知道有多少个对象有待改变时,应该考虑使用观察者模式。
10、抽象工厂模式(Abstract Factory)--就不能不换DB吗--,提供了一个创建一系列相关或相互依赖的接口,而无需指定他们具体的类。它使得更换产品的系列更加容易(如更换数据库)。
11、状态模式(State)--无尽加班何时休--,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。当一个对象的行为取决于它的状态,并且必须在运行时刻根据状态改变他的行为时,就可以考虑使用状态模式了。
12、适配器模式(Adapter)--在NBA我需要翻译--,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于原本接口不兼容而不能一起工作的那些类可以一起工作。适配器主要应用于希望复杂一些现存但接口不匹配的类。
13、备忘录模式(Memonto)--如果再回到从前--,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。适用于需要维护或记录历史属性的类。
14、组合模式(Composite)--分公司,部门--,将对象组合成树形结构以表示部分整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。应用于需求中体现部分与整体层次结构时。
15、迭代器模式(Iterator)--想走?可以!先买票--,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。当你需要遍历一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
16、单例模式(Singleton)--有些类也需计划生育--,保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多少个对象,一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
17、桥接模式(Bridge)--手机软件何时统一--,将抽象部分和它的实现部分分离,使它们都可以独立的变化。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合。
18、命令模式(Command)--烤羊肉串引来的思考--,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如测小/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
19、职责链模式(Chain of Responsibility)--加薪非要老总批--,使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构。结构是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接收者的引用。
20、中介者模式(Mediator)--世界需要和平--,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。由于中介者对象控制了集中化,于是就把交互的复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个对象都有复杂。
21、享元模式(Flyweight)--项目多也别傻做--,运用共享技术有效地支持大量细粒度的对象。如果发现许多实例除了几个参数外基本都是相同的,那么可以考虑把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少实例的数目。
22、解释器模式(interperter)--其实你不懂老板的心--,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。如果一种特定类型的问题发生的频率足够高,那么可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
23、访问者模式(Vistor)--男人和女人-- ,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式把处理从数据结构分离出来,适用于有比较稳定的数据结构,又有易于变化的算法。