前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >《实现模式》读书总结

《实现模式》读书总结

作者头像
wxdut.com
发布于 2018-05-09 09:35:36
发布于 2018-05-09 09:35:36
97600
代码可运行
举报
文章被收录于专栏:王肖的UT王肖的UT
运行总次数:0
代码可运行

这是一本关于如何写好代码的书,是一本关于“如何编写别人能懂的代码”的书。

关于这本书

  1. 作者简介 Kent Beck,软件开发方法学的泰山北斗,是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一,更是极限编程和测试驱动开发的创始人。
  2. 这本书的目标 这本书的目标是帮助你通过代码表达自己的意图。
  3. 章节概览

模式

举个栗子? 编程中,我们想写一个函数,需要给它命名。那么映入我们脑海的是:

  1. 模式让你感觉到束手束脚,但可以帮你节省时间和经历,提高效率。
  2. 模式的种类繁多,众多模式构成了一种编程风格

一种编程理论

价值观

原则

小结

上面提到了个关键词,分别是:模式、原则、价值观。

模式是编码是的一些约束(force),众多的模式共同构筑了一种编程风格。

价值观是编程过程中统一支配性主题,影响了我们在编程中所作的每个决策。

原则是模式和价值观之间搭建的桥梁,在遇到没有现有模式可以解决的问题的时候,原则往往可以让我们“无中生有”的创造一些东西,而这些东西往往都是很不错的。

摘录书中的一句总结:模式描述了要做什么,价值观提供了动机,原则把动机转化成了实际行动。

动机

由上面的讨论可以知道,价值观为模式的形成提供了动机。那么主要的动机之一是软件设计应该致力于减少整体成本。

\[ cost_{total} = cost_{develop} + cost_{maintain} \]

经过统计,人们发现,维护成本远远高于初始成本。也就是说维护的代价很大。因为理解现有代码需要耗费很多时间,而且容易出错,改动之后还需要重新测试和部署。

\[ cost_{maintain} = cost_{understand} + cost_{change} + cost_{test} + cost_{develop} \]

通过合理的模式的使用,可以降低经济成本。

关于类,书中讲解了很多细小的点。有的比较有意思,值得一说。

通读本章后,进行了梳理整合,做如下总结。

  1. 类的命名 类的名字应该是简明扼要,简短而有表现力。一个好的命名可以大大增加理解代码的容易度。
  2. 针对接口编程,不针对现实编程 对操作进行抽象,由子类实现各自的具体逻辑。 interface(接口)对扩展开放,对修改关闭。比如想给一个interface增加一个函数,不能直接添加, 要重新写个interface继承它。如果直接在原interface增加函数,就要导致所有实现了本接口的地方都要修改,这个代价是非常大的。
  3. 当我们从其他地方复制了一大段代码 如果有两个地方的代码非常相似甚至相同,那就要考虑是否可以抽取到公共父类或者工具类中。直接拷贝一份的弊端很明显,维护起来很困难,比如其中一个地方需要修改,那么另外一个地方是不是也要修改呢。而且增加了代码的阅读难度,这明显和模式的原则不符。
  4. 内部类和匿名内部类 内部类当被实例化之后,会获得创建它的外部类对象的引用,所以可以直接访问后者的数据而不用建立额外的连接。 但是这中对象持有操作有内存泄漏的风险。比如在手Q中ThreadManager.post中就有特殊的操作来避免内存泄漏。
  5. 逻辑委派和可插拔的选择器 把相同的逻辑统一处理,然后把不同的逻辑发放给不同的模块去处理。在手Q中,不同的回报消息在统一处理之后发放给不同的回调逻辑,也是一种实际应用。

可插拔的选择器和逻辑委派很相似,比如有一个打印类的函数列表的工具方法,传给它不同的类名,就打印不同的类的函数信息。

  1. 类库 把一些公共的方法放到一个公共的类中,声明为static,当成工具来调用。可以简化代码,看起来更清晰。

状态

  1. 直接访问与间接访问 在类中有很多变量,每一个变量都会存在很多状态,比如boolean有true和false两种状态,一般类的范围内进行直接访问,对外部的访问一般强制间接访问,也就是通过public的函数访问。 比如下面这种方式一般是类内访问。 door.isOpen = true 而下面这种方式一般用在类外访问。 public boolean isOpen() { return this.isOpen; } 其实就是合理使用Java中的private、protected、public修饰。
  2. 变量的分块 在一个类中有很多变量,比如private成员变量、static静态变量、public公共变量,除了变量名命名要规范外,还要分区分块。比如static类型的应该放到最上面,并且与其他类型的变量隔开。
  3. 参数 一个变量想传递到其他地方有很多方法。比如可以设置成public+static,让别人直接访问。但是这种方式耦合程度太高,比如改一个变量名,所有引用的地方都要修改。可以使用参数,直接把一个状态传递到另外一个地方,而不涉及二者之间的耦合。
  4. 变量的初始化:及早初始化和延迟初始化 初始化就是给变量一个默认的状态。 对于对性能影响较低的初始化可以及早初始化,可以保证变量在后续的使用过程中是已经初始化了的。并且变量的初始化要尽量放到一起,这样逻辑更清晰,也更美观。比如Android中的findViewById()在初始化时就要尽量放到一起。 延迟初始化是考虑到了性能问题,如果初始化成本很高,就可以考虑通过延迟初始化来实现快速启动。

行为

  1. 主体流 虽然Java是面向对象编程,但是在一个函数中,也是由上到下依次执行。主体流中包含了一些异常判断和卫述句(guard clause)。
  2. 卫述句 卫述句是异常检查的一种方式。在程序的主体流中,需要判断某些不适用主体流的情况。 void init() { if (isInited) { return; } .... } 我们习惯了if-then-else这种约束,当看到if的时候,很容易就想到需要else语句。卫述句则不需要else子句,它是表达的另一种情形,只是一次主体流中的异常判断。
  3. 异常传播 当程序发生异常,不能直接将日志信息输出,这样被有心之人抓取到了会产生安全隐患。同样也不能置之不理,这样后面排查问题就很困难。正确的做法是调用异常处理工具,比如写入日志文件等等。

方法

把大块的逻辑分成许多块,每一块都是一个方法,每个方法起一个顾名思义的名称。这样的代码理解起来更容易,更易于维护和重用。

  1. 安全复制 如果在一个类中有一个List,存放着若干个类Demo的对象实例,比如 List<Demo> list = new ArrayList<Demo>(); 如果外界想访问这个列表呢,通常的做法是这样的 public List<Demo> getDemoList() { return this.list; } 这样的话会有安全隐患,我们必须要考虑,外界的逻辑是否会对我们的数据产生影响 getDemoList().clear(); // 数据被莫名修改,会发生一些问题。 考虑更高的安全性,我们可以这么做 public List<Demo> getDemoList() { List<Demo> copyList = new ArrayList<Demo>(); copyList.addAll(this.list); return copyList; } 当然,安全复制不可滥用,如果数据很大,这种复制会占用耗费的内存和性能,所以更好的做法是综合考虑安全性和性能的平衡。
  2. 方法注释 对于沟通良好的代码来说,很多注释完全是多余的。在强调命名的沟通性和表达性的时候,注释显得处在一个很别扭的层次上。注释不是越多越好,在必要的时候添加适当的注释是合理的。当然,在后期的代码修改的时候,记得及时更新代码注释,否则注释不正确反倒对阅读人造成了误解。

容器

  1. 使用容器应该关心的一个问题 在将容器暴露给外界使用的时候,需要考虑外界是否可以对容器进行修改。比如Iterable无法保证容器中的数据不被修改,外界可以直接调用它的remove方法进行修改,而不通知容器所有者,这样会出现问题。解决办法之一就是返回一个安全拷贝。
  2. 不可变的容器 当只想把容器暴露给外界而不希望被修改时,除了安全拷贝外,还可以创建不可修改的容器,当容器的元素被外界修改时,程序会throw exception。
  1. 容器的继承和委派

有时候我们可能需要继承一个容器类。比如新建一个书籍列表的类Library,我们的目的是给他提供类似集合一样的增删改查操作。一个很直接的想法是让它继承ArrayList。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Library extends ArrayList{
    ....
}

这种操作实现了Library的add、remove、迭代以及其他容器操作,但是这种方式会带来一些问题。比如一般我们不需要ArrayList的toArray操作,但是如何避免用户调用呢,总不能把所有不需要的方法都加以实现并抛出UnsupportedOperationException来取消继承。

这里可以使用委派来实现这种操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Library{
    Collection<Book> books = new ArrayList<Book>();
}

使用这种方式可以只暴露一些需要的方法。我在头像墙widget中就是这样做的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class AvatarWallViewPager{
    protected RollViewPager mViewPager;
}

改进框架

  1. 更新框架时的向前兼容性 在更新框架的时候,一个非常重要的点就是向后兼容。更新框架的功能不能影响到现有代码的逻辑。在设计框架的时候,保持代码尽可能简单的同时,也要尽可能提高代码的适用范围,考虑后续框架的更新是否容易。
  2. 兼容性更新--增量式更新 包(package)为框架代码的增量式更新提供了一条途径,可以在新的包下创建相同类名的新类。比如把更新后的org.junit.Assert放到org.junit.improved.Assert这个类中,这样的话客户代码只需要更新imports语句就可以实现更新。修改import更加简单,影响更小。
  3. 抽象--接口和抽象类 多使用接口和抽象类可以提高框架的灵活度。只将必要的逻辑暴露给外部使用,内部逻辑是private的。当修改框架代码时,只要接口和抽象类的抽象方法不变,其他的逻辑可以灵活修改,外部调用者不会受到任何影响。

附录 A

这部分主要是介绍了一个度量操作性能的框架。介绍了设计框架时要注意的一些事情。

设计操作度量框架要注意以下几个要点:

  1. 将操作执行多次,取平均值,克服精度问题。
  2. 在测量时要考虑Java的自动优化机制会不会影响操作执行的时间。

总结

这本书主要是着力于编程时的思维层面上的考虑。开发者大脑中要时刻铭记沟通、简单、灵活的价值观,遵循实现模式,并学会在遇到前所未有的问题时,能在价值观的指导下,利用现有原则找到更为恰当的解决方案。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/4/6,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《实现模式》读书总结
MelonTeam
2018/01/04
1.6K0
《实现模式》读书总结
《实现模式》读书总结
导语 这是一本关于如何写好代码的书,是一本关于“如何编写别人能看懂的代码”的书。从价值观、原则、模式三个层面解读如何优化代码结构,减少代码维护成本。 关于这本书: 作者简介 Kent Beck,软件开发方法学的泰山北斗,是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一,更是极限编程和测试驱动开发的创始人。 这本书的目标 这本书的目标是帮助你通过代码表达自己的意图。 章节概览 图:章节概述 模式 模式就是我们在编写代码时固定的规则(force)。 图:模式 举个栗子:chestnut:
淡定
2018/01/15
5330
❤️设计模式肝完了,还挺全!腾讯和阿里的offer已拿!❤️
金九银十已经来了,挺近大厂最好的机会已经来了!如果你是要找工作的,一定要抓住这个机会!
全栈程序员站长
2022/06/29
2680
❤️设计模式肝完了,还挺全!腾讯和阿里的offer已拿!❤️
华为高级Java面试真题
Java内存模型中的happens-before原则是指在多线程环境下,对一个变量的写操作happens-before于后续对该变量的读操作,这确保了对共享变量的修改能够被其他线程及时感知到。happens-before原则定义了在并发编程中对内存可见性和执行顺序的保证。
林老师带你学编程
2024/01/03
1700
【设计模式】学习笔记(三)——结构型设计模式
由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
鸡先生
2022/10/29
7500
【设计模式】学习笔记(三)——结构型设计模式
设计模式
静态内部类实现方式(也是一种赖加载方式) public class SingletonDemo04 { private static class SingletonClassInstance { private static final SingletonDemo04 instance = new SingletonDemo04(); } public static SingletonDemo04 getInstance() { return SingletonClassInstance.instance; } private SingletonDemo04() {
海仔
2019/08/06
6480
面试 设计题_设计模式面试题及答案
察者方法 public void removeObserver(Observer obs) { list.remove(obs); }
全栈程序员站长
2022/09/30
8330
面试 设计题_设计模式面试题及答案
java---设计模式(重点!!!)
以上IO实例中使用了一个非常经典的设计模式,装饰者设计模式,解决是类在不使用继承的情况下对类的功能进行扩展。
用户10787181
2023/10/17
1920
java---设计模式(重点!!!)
设计模式实战-迭代器模式
迭代器是为容器服务的,那什么是容器呢? 能容纳对象的所有类型都可以称之为容器,例如Collection集合类型、Set类型等,迭代器模式就是为解决遍历这些容器中的元素而诞生的
JavaEdge
2018/10/11
7080
设计模式实战-迭代器模式
设计模式 | 单例模式
它是 23 种设计模式中,属于创建型模式,最为简单的一种设计模式,也是最常用的一种设计模式。这种模式确保同类只有一个实例存在,并提供应用程序的任何其他部分对这个类进行单点访问。
程序员小榆
2024/04/03
960
设计模式 | 单例模式
Java设计模式之迭代器模式
老板让我打印各个项目的报表,包括项目名称,人数,开销等信息,这个好办,看下面的类图:
CoderJed
2018/11/09
7980
23种常用设计模式快速入门教程
设计模式是一组有用的解决方案,用于解决特定类型的软件设计问题。它们通常提供了一种抽象出来的方式,来表达应用程序中常见问题的解决方案,从而帮助开发者更有效地解决问题。设计模式的用途是帮助开发者解决软件设计问题,提高开发效率,降低开发成本,提高代码质量和可维护性,以及更好地管理和理解复杂的系统。设计模式的优点是可以提高代码可维护性,减少代码重复,提高开发效率,降低开发成本,提高代码质量和可维护性,以及更好地管理和理解复杂的系统。设计模式的缺点是可能会使代码变得复杂,也可能会过度设计。设计模式的出处是由GoF(Gang of Four)在1995年发表的著作“设计模式:可复用面向对象软件的基础”中提出。
jack.yang
2025/04/05
1600
Java IO 装饰者模式
  装饰模式以对客户端透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。
intsmaze-刘洋
2018/08/29
4660
Java IO 装饰者模式
Head First设计模式——装饰者模式
前言:对于设计模式我们有时候在想是否有必要,因为实际开发中我们没有那么多闲工夫去套用这么多设计模式,也没有必要为了模式而模式。
SpringSun
2020/08/11
3860
Head First设计模式——装饰者模式
深入设计模式-代理模式
代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
chenchenchen
2020/05/26
8200
23种设计模式汇总概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。 设计模式分类: 创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。 不常用的有:原型模式。 结构型模式:把类或对象结合在一起形成一个更大的结构。 常用的有:代理模式、桥接模式、装饰者模式、适配器模式。 不常用的有:门面模式、组合模式、享元模式。 行为型模式:类和对象如何交互,及划分责任和算法。 常用的有:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式。 不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式。
共饮一杯无
2022/11/28
5180
23种设计模式汇总概述
JAVA面试备战(十七)--设计模式
单例模式用于Runtime,Calendar和其他的一些类中。“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象
程序员爱酸奶
2022/06/06
4040
JAVA面试备战(十七)--设计模式
迭代器模式 Iterator 行为型 设计模式(二十)
在计算机中,Iterator意为迭代器,迭代有重复的含义,在程序中,更有“遍历”的含义
noteless
2018/12/26
3560
C++设计模式——Decorator装饰器模式
装饰器模式是一种结构型设计模式, 它允许在不改变现有对象的情况下,动态地将功能添加到对象中。
Coder-ZZ
2024/06/18
2240
C++设计模式——Decorator装饰器模式
你真的需要手写迭代器吗?迭代器模式原理、JDK 实现与最佳实践指南
行为型,Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.(它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。)
JavaEdge
2021/12/07
3740
你真的需要手写迭代器吗?迭代器模式原理、JDK 实现与最佳实践指南
相关推荐
《实现模式》读书总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验