重构改善既有代码的设计-学习(一):封装

1、封装记录(Encapsulate Record

 

        一些记录性结构(例如hash、map、hashmap、dictionary等),一条记录上持有什么字段往往不够直观。如果其使用范围比较宽,这个问题往往会造成许多困扰。所以,记录性结构应该被封装成为一个类。

        例如:

organization = {name: "Acme Gooseberries", country: "GB"};

        应该被重构为:

class Organization {constructor(data) {this._name = data.name;this._country = data.country;}get name() {return this._name;}set name(arg) {this._name = arg;}get country() {return this._country;}set country(arg) {this._country = arg;}
}

 2、封装集合(Encapsulate Collection)

 

        我们通常鼓励封装,但封装时人们常常犯一个 错误:只对集合变量的访问进行了封装,但依然让取值函数 返回集合本身。这使得集合的成员变量可以直接被修改,而封装它的类则全然不知,无法介入。

        修改的方式是,在类上提供一些修改集合的方法(通常是“添加”、“删除”等),这样就可以使对集合的修改必须经过类。

        例如:

class Person {get courses() {//这里直接把对象本身返回了,在哪里偷偷摸摸被改了都不知道return this._courses;}  set courses(aList) {this._courses = aList;} 
}

        应该改为:

class Person {get courses() {return this._courses.slice();}// 提供修改对象的方法,想改,就必须用类的方法addCourse(aCourse) { ... }removeCourse(aCourse) { ... }
}

3、以对象取代基本类型(Replace Primitive with Object)

 

        不要执着于用基本类型,应该把一些数据封装成对象。

        例如,本身“图案”这个字段可能只是一个字符串,用来存储一个链接,但后来随着业务的逐渐复杂,开始有尺寸、文案等等,那他们就应该被抽取出来,放在一个类里面。

4、以查询取代临时变量(Replace Temp with Query)

 

        如果一个变量只声明一次之后不再被改变,那就别再声明变量了,而是直接用一个查询操作取代他。比如:

// 这里的变量只用了一次
const basePrice = this._quantity * this._itemPrice;if (basePrice > 1000)return basePrice * 0.95;
elsereturn basePrice * 0.98;

        应该变为 :

// 构建一个查询用来替代那个变量
get basePrice() {this._quantity * this._itemPrice;}...if (this.basePrice > 1000)return this.basePrice * 0.95;
elsereturn this.basePrice * 0.98;

 5、提炼类(Extract Class)

        在实际工作中, 类会不断成长扩展。设想你有一个维护大量函数和数据的类。这样的类往往 因为太大而不易理解。此时你需要考虑哪些部分可以分离出 去,并将它们分离到一个独立的类中。如果某些数据和某些 函数总是一起出现,某些数据经常同时变化甚至彼此相依, 这就表示你应该将它们分离出去。

6、内联类(Inline Class)

 

        当一个类因为某种原因开始萎缩(可能是因为一些重构动作移走了这个类的责任),不再承担足够责任,那么他不再有单独存在的理由。应该将“萎缩类”塞进另一个类中。“另一个类”应该是和“萎缩类”关联最紧密的那个类。

7、隐藏委托关系(Hide Delegate)

 

        如果某些客户端先通过服务对象的字段得到另一个对象(受托类),然后调用后者的函数,那么客户就必须知晓这一层委托关系。万一受托类修改了接口,变化会波及通过服务对象使用它的所有客户端。我可以在服务对象上放置一个简单的委托函数,将委托关系隐藏起来,从而去除这种依赖。这么一来,即使将来委托关系发生变化,变化也只会影响服务对象,而不会直接波及所有客户端。

        例如:现在有两个类,代表“人”的Person和代表“部门”的Department。有些客户端希望知道某人的经理是谁,为此,它必须先取得Department对象。

// 客户端必须知道 要调部门 才能知道经理
manager = aPerson.department.manager;

        这样的编码就对客户端揭露了Department的工作原理,于是客户知道:Department负责追踪“经理”这条信息。如果对客户隐藏Department,可以减少耦合。为了这一目的,我在Person中建立一个简单的委托函数。

class Person {get manager() {// 将部门这层封装起来,使客户端不感知return this.department.manager;}
}manager = aPerson.manager;

8、移除中间人(Remove Middle Man)

 

        刚刚谈到了“封装受托对象”的好处。但是这层封装也是有代价的。每当客户端要使用受托类的新特性时,你就必须在服务端添加一个简单委托函数。随着受托类的特性(功能)越来越多,更多的转发函数就会使人烦躁。服务类完全变成了一个中间人,此时就应该让客户直接调用受托类。
        很难说什么程度的隐藏才是合适的。6个月前恰如其分的封装,现今可能就显得笨拙。重构的意义就在于:你永远不必说对不起——只要把出问题的地方修补好就行了。

        做法就是把7中的例子反过来……

9、替换算法(Substitute Algorithm)

        改进算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/418720.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hive-SQL语法大全

Hive SQL 语法大全 基于语法描述说明 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION] path; SELECT expr, ... FROM tbl ORDER BY col_name [ASC | DESC] (A | B | C)如上语法,在语法描述中出现: [],表示可选,如上[LOCATI…

Python-基础篇-数据结构-列表、元组、字典、集合

文章目录 思维导图❓ 大抵是何物数据结构切片 💬具体是何物列表💻 list💻 [ ]自我介绍精神面貌使用说明生理体征增删查改 方法汇总 元组💻 tuple💻 ( )自我介绍使用说明精神面貌生理体征增删查改 字典💻 di…

第三课:GPT

文章目录 第三课:GPT1、学习总结:GPT出现的原因GPT的方法原理目前存在的问题无监督的预训练优化目标模型结构 监督微调课程ppt及代码地址 2、学习心得:3、经验分享:4、课程反馈:5、使用MindSpore昇思的体验和反馈&…

qt学习:QT对话框+颜色+文件+字体+输入

目录 概述 继承图 QColorDialog 颜色对话框 QFileDialog 文件对话框 保存文件对话框 QFontDialog 字体对话框 QInputDialog 输入对话框 概述 对于对话框的功能,在GUI图形界面开发过程,使用是非常多,那么Qt也提供了丰富的对话框类QDia…

前端实现贪吃蛇功能

大家都玩过贪吃蛇小游戏,控制一条蛇去吃食物,然后蛇在吃到食物后会变大。本篇博客将会实现贪吃蛇小游戏的功能。 1.实现效果 2.整体布局 /*** 游戏区域样式*/ const gameBoardStyle {gridTemplateColumns: repeat(${width}, 1fr),gridTemplateRows: re…

【极光系列】springBoot集成elasticsearch

【极光系列】springBoot集成elasticsearch 一.gitee地址 直接下载解压可用 https://gitee.com/shawsongyue/aurora.git 模块:aurora_elasticsearch 二.windows安装elasticsearch tips:注意es客户端版本要与java依赖版本一致,目前使用7.6…

python开发之远程开发工具对比

前言 除了本地开发外,还有一种常见的开发方式就是远程开发,一般情况是一台Windows或mac笔记本作为日常使用的电脑,另有一台linux服务器作为开发服务器。开发服务器的性能往往较强,这样远程开发的方式一方面可以让我们在习惯的系统…

yum下载源,vim使用

文章目录 yum本地配置lzrsz命令行互传scp(远程拷贝)vim yum本地配置 [rootiZf8z3j2ckkap6ypn717msZ ~]# pwd /root [rootiZf8z3j2ckkap6ypn717msZ ~]# ls /etc/yum.repos.d CentOS-Base.repo epel.repo //本地配置源yum会根据/etc/yum.repo.d路径下的配置文件来构成自己的下载…

【设计模式】文件目录管理是组合模式吗?

组合模式是什么? 组合模式是一种将对象组合成树形结构以表示"部分-整体"的层次结构的设计模式。它使得用户对单个对象和组合对象的使用具有一致性。 组合模式在什么情况下使用? 当你发现你需要在代码中实现树形数据结构,让整体-部…

Spring Boot 3.2.2整合MyBatis-Plus 3.5.5依赖不兼容问题

问题演示 导依赖 当你启动项目就会 抛出该异常 java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanObjectType: java.lang.String 问题原因 mybatis-plus 中 mybatis 的整合包版本不够导致的 解决方案 排除掉mybatis-plus 中 mybatis 的整合…

Autosar PRport 在Simulink中的使用

文章目录 前言模型及Autosar接口配置Autosar接口模型接口 生成代码分析总结 前言 在之前使用Simulink开发Autosar模型时,大部分使用的RTE接口都是Sender or Receiver接口。但如果是对于那些具有存储需求的接口来说,一个sender接口需要有另外一个receive…

list列表可编辑状态

有时候list需要修改或选择属性,mfc自带的只能显示内容,基本上是不可以修改,为了实现这个功能需求,需要完成一下步骤转换. 第一步记录选择的单元格. 第二步创建一个编辑框CComboBox对象, 设置字体,窗口属性. 第三步获取选中单元格的位置信息. 第四步获取单元格内容信息. 第五步…