开始看重构

第六章 重新组织函数

提炼函数(Extract Method)

有局部变量

  1. 只读局部变量的值,并不修改它
  2. 对局部变量再赋值
    局部变量只在被提炼的代码段中使用
    局部变量在被提炼的代码之外使用:让目标函数返回该变量的值

内联函数(Inline Method)

去掉某个函数直接使用其中的代码

内联临时变量(Inline Temp)

有一个临时变量只被一个简单的表达式赋值一次,将所有对该变量的引用动作,替换为对他赋值的那个表达式自身

以查询取代临时变量(Replace Temp With Query)

以一个临时变量存储某一表达式的运算结果,将这个表达式提炼到独立函数中,将这个变量的所有引用替换为对新函数的调用

引入解释性变量(Introduce Explain Variable )

将复杂表达式的结果放进一个变量,用这个变量的名称来解释该复杂表达式的用途

分解临时变量(Split Temporary Variable)

对一个临时变量的赋值超过一次,但是这个变量不是循环变量,也不用于收集结果,针对每一次赋值,创造一个新的独立的临时变量

移除对参数的赋值(Remove AssignMents Parameters)

代码对一个参数赋值,以一个临时变量取代该参数的位置

按引用传递 按值传递

以函数对象取代函数

(好复杂) 大概是把临时变量作为类的成员变量进行赋值

替换算法

将函数本体替换为另一个算法

第七章

搬移函数(Move Method)

在该函数经常引用的类中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数,或是将旧函数完全移除
在这里插入图片描述

搬移字段(Move Field)

程序中,某个字段被常驻类之外的另一个类更多的用到
在目标类新建一个字段,修改源字段的所有用户,使他们使用目标类的新字段
如果源字段被很多地方调用,可以先自我封装(Self Encapsulate Filed),即把为源字段封装到一个访问函数,这样在搬移字段后,就只需要修改访问函数。
在这里插入图片描述

提炼类(Extract Class)

某个类做了两个类应该做的事情
建立一个新类,将相关字段和函数搬移到新类
在这里插入图片描述

需要考虑的:要不要对用户公开这个新类

  1. 隐藏这个新类
    在旧类中建立对新类的委托,即对新类的操作全部依赖旧类,从而完全隐藏这个新类
  2. 公开这个新类(可以只在一个包中公开)
    公开这个新类,则无法感知是谁修改了新类的字段
    解决理念:
  • 将新类完全公开,旧类成为新类的引用点
  • 必须通过旧类的对象修改新类对象,将新类设置为不可修改的或是提供一个不可修改的接口

将一个类分成两个类可以对两个对象分别加锁,但如果要确保两个对象同时被锁定,就面临事物问题

内联类(Inner Class)

某个类没有做太多事情,将这个类的所有特性搬移到另一个类,然后移除愿类。
在这里插入图片描述

隐藏委托关系(Hide Delegate)

客户通过一个委托类来调用另一个对象
在服务类上建立客户所需的所有函数,以隐藏委托关系
在这里插入图片描述
可以在服务类上面放置一个简单的函数,从而将委托关系隐藏起来,委托类变化时,只需服务类做出相应的修改,客户是没有感知的
在这里插入图片描述

移除中间人(Remove Middle Man)

某个类做了过多的委托动作,让客户直接调用委托类
当委托类的功能越来越多,每次都必须在服务类建立委托函数,服务类完全变成一个中间人,这个时候可以让客户直接调用委托类。
在这里插入图片描述

引入外加函数(Introduce Foreign Method)

你需要为提供服务的类新增一个函数,但你无法修改这个类。
在客户类中建立一个函数,并以第一参数的形式传入一个服务实例

这种情况适用于,抽象多次使用的函数,减少重复代码

public static void main(String[] args) { 
        Date now = new Date();
        Date newStart = new Date(now.getYear(), now.getMonth(),now.getDate()+1);
        Date newStart1 = nextDate(now);
    }
    public static Date nextDate(Date date){
        return new Date(date.getYear(), date.getMonth(),date.getDate()+1);
    }

引入本地扩展(Introduce Local Extension)

你需要为提供服务的类新增一些额外函数,但你无法修改这个类。
建立一个新类使他包含这些额外函数,让这个拓展品成为源类的子类或是包装类
在这里插入图片描述
这里将子类化(subclassing)和包装(wrapping)统一称为本地拓展

  • 本地拓展是一个独立的类,但也是被拓展类的一个子类型;
  • 它提供源类的一切特性,同时额外添加新特性;
  • 在任何使用源类的地方都可以使用本地拓展取而代之;

  • 子类创建的工作量少
    缺点
  • 子类需要在对象创建期实施,不能在对象创建后再使用本地拓展
  • 子类化方案还必须产生一个子类对象,这种情况如果引用了旧对象就同时有两个对象保存源数据,会产生数据不一致问题,这种情况用包装类

  • 包装类需要为源类所有的函数提供委托函数

使用包装类有一个特殊的问题:如何处理接受原始类为参数的函数
解决办法:使包装类向上兼容,即让包装类重写这类函数,使他即接收原始类又接收包装类,这样重写可以向用户隐藏包装类。
但是对于某些系统函数会出问题,比如equal

//在包装类中重写比较方法
public booolean equals(Date arg)

这样重写会违背java的交换定律,即a.equals(b)为true,那b.equals(a)也为true
这种时候只有向用户表示进行了包装

//在包装类中重写比较方法
public booolean equalsDate(Date arg)
public booolean equalsDate(DateWrap arg)

而子类化方案中不重写原始类的函数将藕不会出现这种问题

重新组织数据

自封装字段(Self Encapsulate Filed)

直接访问一个字段会使字段之间的耦合关系变得臃肿
为这个字段设置取值设值函数,并且只以这些函数来访问字段

间接访问变量的好处:
子类可以通过覆写一个函数而改变获取数据的途径
还支持更灵活的数据管理方式,比如延迟初始化

注意:
在构造函数中使用设值函数的情况,一般来说设值函数被认为应该在对象创建后再使用,所以初始化过程的行为与设值函数的行为不同。对于该字段要么设置专门的初始化函数,要么允许在构造函数中直接访问该字段。

以对象取代数据值(Replace Date Value With Object)

有一个数据项需要与其他数据和行为一起使用才有意义,将数据项变为对象

将值对象改变为引用对象(Change Value To Reference)

从一个类中衍生出许多彼此相等的实例,希望他们替换为同一个对象,将这个值对象变成引用对象

对象的分类:值对象、引用对象
值对象:完全由其所含的数据值来定义,比如钱、日期等,我们并不介意值对象的副本的存在,对值对象的比较需要覆写equal和hashcode方法
引用对象:代表真实世界中的一个事物,比如客户、账户这些东西,可以直接用==操作符来检查两个对象是否相等

在一个值对象中保存了少量不可修改的数据,然后想给这个对象加入一些可修改的数据,并且确保对任一有对象修改都能影响到引用此对象的地方,这时需要把值对象变为引用对象

将引用对象改变为值对象(Change Reference To Value)

引用对象必须被某种方式控制,我们总是需要向其控制者请求合适的引用对象---->
造成内存之间错综复杂的关系

值对象的特性:不可变,无论何时,只要调用同一对象的同一个查询函数,都应该得到同样的结果。保证了这一点,就可以放心的以多个对象表示同一事物。
如果值对象是可变的,这样就必须保证对某一对象的修改会自动更新其他“代表相同事物”的对象,这样还不如把它变成引用对象

不可变(immutable):有一个Money类表示钱的概念,包含货币和金额两种信息,那Money通常是一个不可变的值对象。
但是这不意味着薪资不可变,意味着如果要改变薪资,需要新建立一个Money对象来取代现有的 Money,而不是在现有的Money上面修改。薪资和Money的关系的可以改变,但是Money自身是不可变的。

以对象取代数组(Replace Array With Object)

数组应该只用于以某种顺序容纳一组相似的对象。
如果有一个数组,其中的元素各自代表不同的东西,以对象替换数组。对数组中的每个元素以一个字段来表示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值