--- title: 秒懂设计模式 description: 本书共计25章,以轻松、幽默、浅显易懂的文风从面向对象编程、面向对象三大特性的理论基础开篇,然后系统且详细地讲解了单例、原型、工厂方法、抽象工厂、建造者、门面、组合、装饰器、适配器、享元、代理、桥接、模板方法、迭代器、责任链、策略、状态、备忘录、中介、命令 keywords: - 秒懂设计模式 - 计算机 tags: - 阅读/计算机 - 阅读/笔记 author: 7Wate date: 2023-07-17 --- ## 简介 - **书名**:《秒懂设计模式》 - **作者**: 刘韬 - **分类**: 计算机-编程设计 - **ISBN**:9787115549365 - **出版社**:人民邮电出版社 ## 概述 本书共计25章,以轻松、幽默、浅显易懂的文风从面向对象编程、面向对象三大特性的理论基础开篇,然后系统且详细地讲解了单例、原型、工厂方法、抽象工厂、建造者、门面、组合、装饰器、适配器、享元、代理、桥接、模板方法、迭代器、责任链、策略、状态、备忘录、中介、命令、访问者、观察者及解释器等23种设计模式的概念及结构机理,最后以六大设计原则收尾,全面地解析归纳了软件设计准则,参透设计模式的本质。本书引入了很多贴近生活的真实范例,并配有大量生动形象的插图,再结合相关例程代码实战演练,循序渐进、深入浅出,引导读者探究设计模式的哲学真谛。本书面向广大的软件设计工作者,包括但不限于各个层次从事面向对象编程语言开发的软件开发、设计、架构等工程技术人员,也可以作为大专院校相关专业教学用书和培训学校的教材。 ## 划线 > 代码量大并不能代表系统功能多么完备,更不能代表程序员多么努力与优秀,反之,作为有思想高度的开发者一定要培养“偷懒”意识,想方设法以最少的代码量实现最强的功能,这样才是优秀的设计。 > 设计模式主要研究的是“变”与“不变”,以及如何将它们分离、解耦、组装,将其中“不变”的部分沉淀下来,避免“重复造轮子”,而对于“变”的部分则可以用抽象化、多态化等方式,增强软件的兼容性、可扩展性。 > 优秀的系统不单单在于其功能有多么强大,更应该将各个模块划分清楚,并且拥有一套完备的框架,像开放式平台一样兼容对各种插件的扩展,让功能变动或新增变得异常简单,一劳永逸,这离不开对各种设计模式的合理运用。 > 从某种意义上讲,设计模式并不是指某种具体的技术,而更像是一种思想,一种格局。 > “封装”“继承”和“多态”便是面向对象的三大特性 > 如果把一些不相干的对象硬生生封装在一起,就会使代码变得莫名其妙,难于维护与管理,所谓“物极必反,过犹不及”,所以封装一定要适度。 > 继承可以使父类的属性和方法延续到子类中,这样子类就不需要重复定义,并且子类可以通过重写来修改继承而来的方法实现,或者通过追加达到属性与功能扩展的目的。从某种意义上讲,如果说类是对象的模板,那么父类(或超类)则可以被看作模板的模板。 > 我们知道任何类都有一个toString()方法,但我们根本没有声明它,这是为什么呢?其实这是从Object类继承的方法,因为Object是一切类的祖先类。 > 多态化的外设使计算机功能更加强大、灵活、可扩展、可替换。其实这就是设计模式中非常重要的一种“策略模式”,接口的定义是解决耦合问题的关键所在。 > 我们都知道有一种设备叫转换器,它能轻松地将老旧的接口设备调制适配到新的接口,以达到兼容的目的,这就是“适配器模式”。 > 单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中、统一的访问接口,以使系统行为保持协调一致。 > 这就是“饿汉模式”(eager initialization),即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。 > 这就是“懒汉模式”(lazy initialization > 这样的好处是如无请求就不实例化,节省了内存空间;而坏处是第一次请求的时候速度较之前的饿汉初始化模式慢,因为要消耗CPU资源去临时造这个太阳(即使速度快到可以忽略不计)。 > 我们一共用了2个嵌套的判空逻辑,这就是懒加载模式的“双检锁”:外层放宽入口,保证线程并发的高效性;内层加锁同步,保证实例化的单次运行。 > Singleton(单例):包含一个自己的类实例的属性,并把构造方法用private关键字隐藏起来,对外只提供getInstance()方法以获得这个单例对象。 > 原型模式可以用对象创建对象,而不是用类创建对象,以此达到效率的提升。 > 对于第一份打印出来的原文稿,我们可以称之为“原型文件”,而对于复印过程,我们则可以称之为“原型拷贝” > 程序设计中的工厂类往往是对对象构造、实例化、初始化过程的封装, > 制造逻辑只是被换了个地方,挪到了简单工厂中而已,并且客户端还要告知产品种类才能产出,这无疑是另一种意义上的耦合。 > 大量的产品判断逻辑代码会被堆积在制造方法中,看起来好像功能强大、无所不能,其实维护起来举步维艰,简单工厂就会变得一点也不简单了。 > 多态化后的工厂多样性不言而喻,每个工厂的生产策略或方式都具备自己的产品特色,不同的产品需求都能找到相应的工厂来满足 > 工厂方法模式不但能将客户端与敌人的实例化过程彻底解耦,抽象化、多态化后的工厂还能让我们更自由灵活地制造出独特而多样的产品。 > 需要注意的是,抽象工厂模式一定是基于产品的族系划分来布局的,其产品系列一定是相对固定的,故以抽象工厂来确立工业制造标准(各产品系列生产接口)。 > 建造者模式又称为生成器模式,主要用于对复杂对象的构建、初始化,它可以将多个简单的组件对象按顺序一步步组装起来,最终构建成一个复杂的成品对象。与工厂系列模式不同的是,建造者模式的主要目的在于把烦琐的构建过程从不同对象中抽离出来,使其脱离并独立于产品类与工厂类,最终实现用同一套标准的制造工序能够产出不同的产品。 > 建造者的各制造步骤与逻辑都应该被抽离出来独立于数据模型, > 我们可以用组合模式来表达“部分/整体”的层次结构,提取并抽象其相同的部分,特殊化其不同的部分,以提高系统的可复用性与可扩展性,最终达到以不变应万变的目的。 > 优雅、巧妙的方式将两侧“对立”的接口“整合”在一起,顺利化解双方难以调和的矛盾,最终使它们顺利接通 > 当系统存在大量的对象,并且这些对象又具有相同的内部状态时,我们就可以用享元模式共享相同的元件对象,以避免对象泛滥造成资源浪费。 > 其实路由器本质上并不具备上网功能,而只是充当代理角色,对访问进行监管、控制与转发。 > 如代码清单12-4所示,客户端(终端设备)一开始创建的并不是“猫”,而是实例化路由器来连接互联网。简单来讲,就是用户只需要知道连接路由器便可以上网了,至于“猫”是什么,用户完全可以无视 > 桥接模式(Bridge)能将抽象与实现分离,使二者可以各自单独变化而不受对方约束,使用时再将它们组合起来 > 拿手机制造来说,芯片可以由美国设计制造,屏幕可以由韩国制造,摄像头则可以由日本制造……最后由中国制造其他半导体组件并完成手机的组装,从而形成手机制造产业链并使产品高效生产 > 抽象方”与“实现方 > 桥接模式将抽象与实现彻底解耦,使形状与颜色的纠葛终被化解,各自为营,互不侵扰。劳动分工实现了各种产品制造的自由扩展,使其能够在各自维度上达成多态,无限延伸。 > 需求分析、软件设计、代码开发、质量测试、上线发布。 > 模板方法模式巧妙地结合了抽象类虚部方法与实部方法,分别定义了可变部分与不变部分,其中前者留给子类去实现,保证了系统的可扩展性;而后者则包含一系列对前者的逻辑调用,为子类提供了一种固有的应用指导规范,从而达到虚中带实、虚实结合的状态。 > 如代码清单16-9所示,一开始我们在第4行构造了财务专员,接着组装了责任链(其实这里还可以交给工作流工厂去构造责任链 > 策略模式让策略与系统环境彻底解耦,通过对算法策略的抽象、拆分,再拼装、接入外设,使系统行为的可塑性得到了增强 > 变化是世界的常态,唯一不变的就是变化本身。 > 备忘录模式(Memento)则可以在不破坏元对象封装性的前提下捕获其在某些时刻的内部状态,并像历史快照一样将它们保留在元对象之外,以备恢复之用。 > 中介模式(Mediator)为对象构架出一个互动平台,通过减少对象间的依赖程度以达到解耦的目的 > 众所周知,对象间显式的互相引用越多,意味着依赖性越强,同时独立性越弱,不利于代码的维护与扩展。中介模式很好地解决了这些问题, > 命令模式(Command)能够将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,以使命令的请求方与执行方解耦,双方只通过传递各种命令过象来完成任务 > 命令模式能使我们在不改变任何现有系统代码的情况下,实现命令功能的无限扩展 > 观察者模式(Observer)可以针对被观察对象与观察者对象之间一对多的依赖关系建立起一种行为自动触发机制,当被观察对象状态发生变化时主动对外发起广播,以通知所有观察者做出响应。 > 总之,不是自己分内之事绝不该负责,这就是单一职责原则(Single Responsibility Principle)。 > 所以我们需要把闪烁控制电路独立出来,灯泡与闪烁之间的通信应该通过接口去实现,从而划清界限,各司其职,这样类封装才变得有意义 > 其中“开”指的是对扩展开放,而“闭”则指的是对修改关闭。简单来讲就是不要修改已有的代码,而要去编写新的代码。 > 所以说符合开闭原则的设计,一定要通过抽象去实现,高层抽象的泛化保证了底层实现的多态化扩展,而不需要对现有系统做反复修改。 > 当系统升级时,如果为了增强系统功能而需要进行大量的代码修改,则说明这个系统的设计是失败的,是违反开闭原则的。 > 此原则指的是在任何父类出现的地方子类也一定可以出现,也就是说一个优秀的软件设计中有引用父类的地方,一定也可以替换为其子类。 > 接口隔离原则要求我们对接口尽可能地细粒度化,拆分开的接口总比整合的接口灵活 > 世界上并不存在无所不能的设计,而且任何事物都有其两面性,任何一种设计模式都有其优缺点,所以对设计模式的运用一定要适可而止,否则会使系统臃肿不堪。满足目前需求,并在未来可预估业务范围内的设计才是最合理的设计。当然,在系统不能满足需求时我们还可以做出适当的重构,这样的设计才是切合实际的。 ## 笔记 > 究其本质,克隆操作时Java虚拟机会进行内存操作,直接拷贝原型对象数据流生成新的副本对象,绝不会拖泥带水地触发一些多余的复杂操作(如类加载、实例化、初始化等),所以其效率远远高于“new”关键字所触发的实例化操作 💭 池复用模式 > 众所周知,对象间显式的互相引用越多,意味着依赖性越强,同时独立性越弱,不利于代码的维护与扩展。 💭 插件系统也是类似 > 设计模式绝不可以被滥用,以免陷入“为了设计而设计”的误区,导致过度设计。 💭 切勿让设计模式成为开发的绊脚石 > 单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则,它们通常被合起来简称为“S.O.L.I.D”原则,也是最为流行的一套面向对象软件设计法则。最后我们再附加上迪米特法则,简称“LoD”。接下来我们将依次研究这六大原则。 💭 设计模式的根本依据 > 在面向对象的软件设计中,人们经常会遇到一些重复出现的问题。为降低软件模块的耦合性,提高软件的灵活性、兼容性、可复用性、可维护性与可扩展性,人们从宏观到微观对各种软件系统进行拆分、抽象、组装,确立模块间的交互关系,最终通过归纳、总结,将一些软件模式沉淀下来成为通用的解决方案,这就是设计模式的由来与发展。 💭 效率 ## 书评 ## 点评