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

news2024/11/14 12:15:46

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;
else
    return basePrice * 0.98;

        应该变为 :

// 构建一个查询用来替代那个变量
get basePrice() {this._quantity * this._itemPrice;}

...

if (this.basePrice > 1000)
    return this.basePrice * 0.95;
else
    return 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.coloradmin.cn/o/1399004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pytest + allure(windows)安装

背景 软硬件环境: windows11,已安装anaconda,python,pycharm用途:使用pytest allure 生成报告allure 依赖java,点击查看java安装教程 allure 下载与安装 从 allure下载网址下载最新版本.zip文件 放在自…

火速收藏!2024 新年微信红包封面领取全攻略

2024“龙”重登场!今年有哪些令人期待的红包封面? 前方大批精美红包封面来袭,全新品牌氛围红包封面上线,支持品牌定制特色氛围元素,沉浸感受浓浓年味儿,收获满满惊喜! 新年开好运,微…

7 python快速上手

数据类型(下) 数据类型(下)1.集合(set)1.1 定义1.2 独有功能1.3 公共功能1.4 转换1.5 其他1.5.1 集合的存储原理1.5.2 元素必须可哈希1.5.3 查找速度特别快1.5.4 对比和嵌套 强插:None类型2.字典…

CloudPanel file-manager/backend/makefile接口存在远程命令执行漏洞CVE-2023-35885

@[toc] 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. CloudPanel 简介 微信公众号搜索:南风漏…

Vulnhub靶机:EvilBox-One

一、介绍 运行环境:Virtualbox 攻击机:kali(10.0.2.15) 靶机:EvilBox-One(10.0.2.25) 目标:获取靶机root权限和flag 靶机下载地址:https://www.vulnhub.com/entry/e…

python中Pytest常用的插件

前言 除了框架本身提供的功能外,Pytest还支持上百种第三方插件,良好的扩展性可以更好的满足大家在用例设计时的不同需求。本文将为大家详细介绍下面5项常用的插件。 1. 用例依赖 编写用例的时候,我们会注意用例之间的独立性,但部…

Python爬虫IP池

目录 一、介绍 1.1 为什么需要IP池? 1.2 IP池与代理池的区别 二、构建一个简单的IP池 三、注意事项 一、介绍 在网络爬虫的世界中,IP池是一个关键的概念。它允许爬虫程序在请求网页时使用多个IP地址,从而降低被封禁的风险,提高…

【2024最新】如何有效搭建自动化测试框架?

前言 最近好多小伙伴都在说接口自动化测试,那么究竟什么是接口自动化测试呢?让我们一起往下看就知道了,首先我们得先弄清楚下面这个问题。 为什么要做(自动化)接口测试? 1、由于现在各个系统的复杂度不断…

Jenkins环境配置篇-更换插件源

作为持续集成的利器 Jenkins 已经得到了广泛地应用,仅仅作为一个工具,Jenkins 已然有了 自己的生态圈,支持其的 plugin 更是超过 1300。在实际中如何使用以及如何更好地使用 jenkins,一直是大家在实践并讨论的。本系列文章将会从如…

正则表达式第三四个作用:替换、切割

目录 方法二 replaceAll: 方法三:spilt: 方法一之前已经见过了: 方法二 replaceAll: 形参中: 参数regex表示一个正则表达式。可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。 代码演示 S…

容器技术1-容器与镜像简介

目录 1、容器与虚拟化 2、容器发展历程 3、镜像简介 4、镜像原理 (1)分层存储 (2)写时复制 (3)内容寻址 (4)联合挂载 1、容器与虚拟化 容器技术在操作系统层面实现了对计算机…

全志D1-H芯片Tengine支持

简介 ​ Tengine 是 OPEN AI LAB 推出的边缘 AI 计算框架,致力于解决 AIoT 产业链碎片化问题,加速 AI 产业化落地。Tengine 为了解决 AIoT 应用落地问题,重点关注嵌入式设备上的边缘 AI 计算推理,为海量 AIoT 应用和设备提供高性…

makefile里面的变量使用,系统变量

文章目录 makefile里面的变量使用 makefile里面的变量使用 calc:add.o sub.o multi.ogcc add.o sub.o multi.o calc.cpp -o calcadd.o:add.cppgcc -c add.cpp -o add.osub.o:sub.cppgcc -c sub.cpp -o sub.omulti.o:multi.cppgcc -c multi.cpp -o multi.oclean:rm -rf *.o cal…

每日一练【最大连续1的个数】

一、题目描述 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 二、题目解析 本题同样是利用滑动窗口的解法。 首先进入窗口,如果是1,就直接让right,但是如果是…

【奶奶看了都会】用AI工具制作微信动态红包封面保姆级教程,附动态红包封面领取

AI一天,人间一年。我是卷福同学,一个在福报厂修过福报的程序员 今年微信红包封面新出了动态封面,点开红包之后是个动图,而且有的还能加上音乐,可以说逼格非常高。假如你在朋友之间发红包用上这么一个封面,朋…

CodeWave学习笔记--采购管理系统

1.CodeWave是什么? CodeWave是一款智能低代码开发平台,基于网易自研拥有大规模参数和深度学习能力的智能模型底座产品架构,为企业级应用提供更加智能化研发的软件生产方式。IT人员可以轻易实现从“智能生成”到“可视化拖拽调整”的全栈低代…

使用Python监听并下载微信聊天表情包

实现的功能 只要有人给你发了表情包,不管是群聊还是个人发的,都将它保存到本地。也许某天斗图的时候就能用到,不过即使有了表情包,还需要一个检索功能,不然这一张一张看也太费眼睛了。 检索表情包 检索表情包的功能…

mariadb数据库从入门到精通

mariadb数据库的安装以及安全初始化 mariadb数据库的安装以及安全初始化 mariadb数据库的安装以及安全初始化一、实验前提二、mariadb数据库的安装三、mariadb数据库安全初始化3.1 设定数据库基本的安全初始化3.2关闭对外开放端口 系列文章目录一、查看数据库二、进入库并且查看…

Python网络爬虫步骤是什么?新手小白必看 !

python网络爬虫步骤:首先准备所需库,编写爬虫调度程序;然后编写url管理器,并编写网页下载器;接着编写网页解析器;最后编写网页输出器即可。 本教程操作环境:windows7系统、python3.9版&#xff…

2024Java高频面试题之MQ消息中间件,面试都问些什么?(附详细答案)

最近很多同学问我有没有java学习资料,我根据我从小白到架构师多年的学习经验整理出来了一份50W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴 可以关注我公众号:“ Tom聊架构 ”, 回复暗号:“ 578”即…