`
381895649
  • 浏览: 232258 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java 代码重构-第一章(分解并重组statement())

    博客分类:
  • java
 
阅读更多

 

上一篇文章:java 代码重构-第一章(起点)

下一篇文章:java 代码重构-第一章(类自己该做自己的事)

 

2.1 把switch代码在方法中抽出

  • 第一个明显引起我注意的就是长得离谱的statement() 。每当看到这样长长的函数,我就想把它大卸八块。要知道,代码区块愈小,代码的功能就愈容易管理,代码的处理和搬移也都愈轻松。

  • 重构过程的第一阶段中,我将说明如何把长长的函数切开,并把较小块的代码移至更合适的class 内。我希望降低代码重复量,从而使新的(打印HTML 报表用的)函数更容易撰写。

  • 第一个步骤是找出代码的逻辑泥团(logical clump)并运用 Extract Method。本例一个明显的逻辑泥团就是switch 语句,把它提炼(extract)到独立函数中似乎比较好。

  • 和任何重构准则一样,当我提炼一个函数时,我必须知道可能出什么错。如果我提炼得不好,就可能给程序引入臭虫。所以重构之前我需要先想出安全作法。

  • 首先我得在这段代码里头找出函数内的局部变量(local variables)和参数(parameters)。我找到了两个:each 和thisAmount,前者并未被修改,后者会被修改。任何不会被修改的变量都可以被我当成参数传入新的函数,至于会被修改的变量就需格外小心。如果只有一个变量会被修改,我可以把它当作返回值。thisAmount 是个临时变量,其值在每次循环起始处被设为0,并且在switch 语句之前不会改变,所以我可以直接把新函数的返回值赋予它。

  • 下面展示重构前后的代码。重构前的代码在下面类对比.凡是从函数提炼出来的代码,以及新代码所做的任何修改,只要我觉得不是明显到可以一眼看出,就以粗体字标示出来特别提醒你。

 

上一篇文章,最开始的代码

Customer 

 

/**
 * 通计清单
 * @return
 */
public String statement(){
    double totalAmount = 0;//合计
    int frequentRentePoints = 0;
    Enumeration<Rental> enu_rentals = rentals.elements();
    String result = "Rental Record for "+ this.getName() + " 
";
    while(enu_rentals.hasMoreElements()){
        double thisAmount = 0;
        Rental each = enu_rentals.nextElement();

        switch (each.getMovie().getPriceCode()) {
        case Movie.REGULAR:
            thisAmount += 2;
            if(each.getDeysRented() > 2){
                thisAmount += (each.getDeysRented() - 2) * 1.5;
            }
            break;
        case Movie.NEW_RELEASE:
            thisAmount += each.getDeysRented() * 3;
            break;
        case Movie.CHILDRENS:
            thisAmount += 1.5;
            if(each.getDeysRented() > 3){
                thisAmount += (each.getDeysRented() -3 ) * 1.5;
            }
            break;
        }

        frequentRentePoints ++;

        if((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDeysRented() > 1){
            frequentRentePoints ++;
        }

        result += "	"+each.getMovie().getTitle() + "	" +String.valueOf(thisAmount) + "
";

        totalAmount += thisAmount;

    }
    result += "Amount owed is " + String.valueOf(totalAmount) + "
";
    result += "You earned " + String.valueOf(frequentRentePoints) + " frequent renter points";
    return result;
}

 

 

跟下面重构的代码对比(Customer 完整代码)

 

package com.mkfree.refactoring.shap1;

import java.util.Enumeration;
import java.util.Vector;

/**
 * 顾客
 * @author hk
 *
 * 2012-12-25 下午10:59:03
 */
public class Customer {

    private String name;
    private Vector<Rental> rentals = new Vector<>();

    public Customer(String name) {
        this.name = name;
    }

    /**
     * 添加
     * @param rental
     */
    public void addRentals(Rental rental){
        rentals.add(rental);
    }

    public String getName() {
        return name;
    }

    /**
     * 通计清单
     * @return
     */
    public String statement(){
        double totalAmount = 0;//合计
        int frequentRentePoints = 0;
        Enumeration<Rental> enu_rentals = rentals.elements();
        String result = "Rental Record for "+ this.getName() + " 
";
        while(enu_rentals.hasMoreElements()){
            double thisAmount = 0;
            Rental each = enu_rentals.nextElement();

            thisAmount = amountFor(each);//计算一笔租片费

            frequentRentePoints ++;

            if((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDeysRented() > 1){
                frequentRentePoints ++;
            }

            result += "	"+each.getMovie().getTitle() + "	" +String.valueOf(thisAmount) + "
";

            totalAmount += thisAmount;

        }
        result += "Amount owed is " + String.valueOf(totalAmount) + "
";
        result += "You earned " + String.valueOf(frequentRentePoints) + " frequent renter points";
        return result;
    }

    /**
     * 把计算一笔租片
     * @param each
     * @return
     */
    private int amountFor(Rental each) { // 计算一笔租片费。
        int thisAmount = 0;
        switch (each.getMovie().getPriceCode()) {
        case Movie.REGULAR: // 普通片
            thisAmount += 2;
            if (each.getDeysRented() > 2)
                thisAmount += (each.getDeysRented() - 2) * 1.5;
            break;
        case Movie.NEW_RELEASE: // 新片
            thisAmount += each.getDeysRented() * 3;
            break;
        case Movie.CHILDRENS: // 儿童。
            thisAmount += 1.5;
            if (each.getDeysRented() > 3)
                thisAmount += (each.getDeysRented() - 3) * 1.5;
            break;
        }
        return thisAmount;
    }

}

 

 

 

每次做完这样的修改之后,我都要编译并测试。这一次起头不算太好——测试失败了,有两笔测试数据告诉我发生错误。一阵迷惑之后我明白了自己犯的错误。我愚蠢地将amountFor() 的返回值型别声明为int,而不是double 。

以上代码就已经消除了switch里的代码...是不是,整个类好看些呢呢?

 

 

本文章来自:http://blog.mkfree.com/posts/18

 

分享到:
评论

相关推荐

    重构-改善既有代码的设计

    1.3 分解并重组statement() 8 1.4 运用多态取代与价格相关的条件逻辑 34 1.5 结语 52 第2章 重构原则 53 2.1 何谓重构 53 2.2 为何重构 55 2.3 何时重构 57 2.4 怎么对经理说 60 2.5 重构的难题 62...

    毕业设计-程序 思创兼职V6.6.5 全开源版-整站商业源码.zip

    毕业设计-程序 思创兼职V6.6.5 全开源版-整站商业源码.zip

    配电网电压与无功优化协调:基于二阶锥规划的多目标函数及场景分析

    内容概要:本文探讨了配电网电压与无功协调优化的问题,旨在通过优化手段最小化运行成本并减少电压偏差。文中介绍了目标函数的构成,包括开关动作成本、功率损耗成本和设备运行成本,并提出了将非凸模型转化为二阶锥规划模型的方法。通过优化变压器分接头位置、电容器接入组数以及SOP的输出功率,实现了电压与无功的有效控制。此外,还对不同场景进行了对比分析,验证了优化策略的效果。 适合人群:从事电力系统研究、配电网管理和优化的专业人士,以及对电力系统优化感兴趣的学者和技术人员。 使用场景及目标:适用于希望深入了解配电网电压与无功协调优化的技术人员,帮助他们掌握优化策略的具体应用,提升电网运行效率和稳定性。 其他说明:文章不仅提供了理论分析,还涉及了具体的模型构建和优化算法实现,有助于读者全面理解配电网优化的实际操作流程。

    毕业设计-红包拓客生意宝V1.6.44 开源版-整站商业源码.zip

    毕业设计-红包拓客生意宝V1.6.44 开源版-整站商业源码.zip

    外转子无刷直流电机温度场特性分析与瞬态热仿真的关键技术及应用

    内容概要:本文详细探讨了外转子无刷直流电机在不同应用场景(如无人机、电动车轮毂)中的温度场特性及其瞬态热仿真方法。首先介绍了电机的主要热源(铜损和铁损),并通过Python代码实现了铜损的精确计算。接着讨论了建模过程中散热边界的设定,特别是在外转子结构中利用ANSYS Fluent进行风冷仿真时需要注意的问题。文中还强调了对流换热系数的合理估算以及瞬态仿真中时间步长的优化设置。最后,通过Python后处理工具生成温度变化曲线,并提供了仿真结果与实际情况不符时的排查建议。 适合人群:从事电机设计、制造及相关领域的工程师和技术人员,尤其是对外转子无刷直流电机感兴趣的研究人员。 使用场景及目标:适用于需要深入了解外转子无刷直流电机温度特性和掌握相关热仿真技能的专业人士。目标是提高电机设计的可靠性和性能,避免因温度过高导致的安全隐患。 其他说明:文章不仅提供了理论分析,还包括具体的代码实现和实践经验分享,有助于读者更好地理解和应用所学知识。

    音乐领域千千阙歌词分析:探讨离别情感与回忆的美好表达方式设计

    内容概要:《千千阙歌》是一首表达离别之情的歌曲,歌词描绘了一对恋人即将分离的情景。歌词中充满了对过去美好时光的回忆和对未来重逢的期待,表达了主人公在离别时刻的复杂情感。通过“红红仍是你,赠我的心中艳阳”、“来日纵使千千阕歌,飘于远方我路上”等诗句,传达了即使未来有再多美好的事物,也无法替代此刻与对方共度的美好时光。歌词反复强调“都比不起这宵美丽”,突出了今夜的独特性和珍贵性。; 适合人群:喜欢抒情歌曲或对离别主题感兴趣的听众。; 使用场景及目标:①适合在离别、感伤的场合播放;②用于表达对过去美好时光的怀念;③适用于想要感受深刻情感共鸣的人群。; 阅读建议:这首歌的歌词富有诗意,情感细腻,建议在安静的环境下聆听,细细品味歌词中蕴含的情感,感受那份对美好时光的留恋与不舍。

    实训商业源码-果蔬识别1.0.4-论文模板.zip

    实训商业源码-果蔬识别1.0.4-论文模板.zip

    毕业设计-oa办公-整站商业源码.zip

    毕业设计-oa办公-整站商业源码.zip

    实训商业源码-柚家政6.1.0+分销插件 1.0.2-论文模板.zip

    实训商业源码-柚家政6.1.0+分销插件 1.0.2-论文模板.zip

    毕业设计-付费阅读5.3.9公众号H5版-整站商业源码.zip

    毕业设计-付费阅读5.3.9公众号H5版-整站商业源码.zip

    MPU6050姿态角解算:二维卡尔曼滤波与DMP引擎方法解析及其应用

    内容概要:本文详细介绍了MPU6050姿态角解算程序的两种主要方法——二维卡尔曼滤波和自带DMP引擎。首先阐述了传感器技术的发展背景下,姿态角解算的重要性和必要性。接着分别讲解了二维卡尔曼滤波的原理、实现步骤以及其特点,强调了它在处理环境噪声和测量噪声方面的优势。然后讨论了自带DMP引擎的姿态角解算程序,指出其直接优化的方式和适用于高精度、实时性强的应用场景。最后总结了两种方法的选择依据,并展望了未来的发展趋势。 适合人群:从事嵌入式系统开发、机器人工程、自动化控制等领域并对姿态角解算感兴趣的工程师和技术爱好者。 使用场景及目标:帮助开发者理解并选择最适合自身项目的姿态角解算方法,特别是在无人驾驶、无人机飞行控制等对精度和实时性有较高要求的应用场景中。 其他说明:文中不仅提供了理论知识,还涉及到了具体的实现细节,有助于读者更好地理解和应用相关技术。

    MATLAB仿真实现Chan法计算TDOA与GDOP评估——无线定位技术研究

    内容概要:本文详细介绍了使用MATLAB进行无线定位技术的研究,重点在于利用Chan法计算TDOA(到达时间差)和GDOP(几何精度稀释因子)。首先解释了TDOA的概念及其在无线定位系统中的重要性,展示了如何通过MATLAB代码实现Chan法计算TDOA的具体步骤。接着阐述了GDOP作为衡量定位系统几何精度的重要指标,演示了不同接收器和信号源位置下GDOP值的计算方法。最后,通过对仿真结果的分析,加深了对无线定位技术原理的理解,并指出了实践中可能遇到的问题和挑战。 适合人群:对无线定位技术和MATLAB有一定了解的研发人员和技术爱好者。 使用场景及目标:适用于需要深入了解TDOA和GDOP计算原理的研究人员,以及希望通过MATLAB仿真提升实践技能的学习者。 其他说明:文中提供了详细的MATLAB代码片段,帮助读者更好地理解和复现实验过程。同时强调了理论与实践相结合的重要性,鼓励读者尝试调整参数以获得更深的理解。

    毕业论文-烟雨图床v2.1.3正式版源码-整站商业源码.zip

    毕业论文-烟雨图床v2.1.3正式版源码-整站商业源码.zip

    毕业论文-智云物业2.3.9-整站商业源码.zip

    毕业论文-智云物业2.3.9-整站商业源码.zip

    实训商业源码-砍价宝7.2.0开源-论文模板.zip

    实训商业源码-砍价宝7.2.0开源-论文模板.zip

    实训商业源码-超人名片小程序2.0.3 原版-论文模板.zip

    实训商业源码-超人名片小程序2.0.3 原版-论文模板.zip

    异步电机矢量控制技术解析:基于DSP、MCU的FOC实现及转子磁场定向控制

    内容概要:本文深入探讨了异步电机的矢量控制技术,特别是Field Oriented Control (FOC) 和转子磁场定向控制。文章介绍了三种不同的FOC实现方案:基于DSP的高精度控制系统、基于MCU的经济实用系统以及详细的Word文档说明。每种方案都包含了具体的代码片段和技术细节,展示了如何通过空间矢量脉宽调制(SVPWM) 实现电机电流的精确控制。此外,还讨论了转子磁场定向控制的关键技术和应用场景,如工业自动化、机器人和电动汽车等。最后,文章总结了这些系统的出色控制效果,并展望了未来的发展方向。 适合人群:电气工程专业学生、电机控制领域的工程师和技术爱好者。 使用场景及目标:适用于希望深入了解异步电机矢量控制技术的专业人士,旨在帮助他们掌握FOC的具体实现方法和应用场景,提高电机控制的精度和效率。 其他说明:文中提供的代码片段和技术细节有助于读者更好地理解和实践FOC系统的设计与实现。

    永磁同步电机二阶线性与非线性自抗扰控制器(ADRC)的Matlab与Simulink建模及三阶观测器研究

    内容概要:本文深入探讨了永磁同步电机的二阶线性模型及其与非线性自抗扰控制器(ADRC)的结合。首先介绍了永磁同步电机的二阶线性模型,通过微分方程描述电机的关键参数与其机械运动状态的关系。接着阐述了ADRC作为一种先进控制算法,在抑制电机高速运转时的振动和噪声方面的作用。随后讨论了Matlab和Simulink在构建模型和仿真中的应用,使研究人员可以实时观察和调整电机的运行状态。最后引入了三阶观测器,用于提高系统性能和稳定性,提供更准确的状态变量反馈。文中还列举了一些相关领域的权威文献和资料,帮助读者深入了解这一主题。 适合人群:对电机控制系统感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于需要理解和掌握永磁同步电机控制策略的研究人员,特别是那些希望利用Matlab和Simulink进行建模和仿真的技术人员。目标是提升对永磁同步电机及其控制策略的理解,增强实际工程应用能力。 其他说明:文中提供的示例代码仅作示意,具体实现需根据实际情况调整。此外,文中引用的相关文献有助于读者进一步深入研究。

    抽水蓄能电站最优调度方案研究:基于粒子群算法的混合发电系统经济调度模型

    内容概要:本文详细探讨了抽水蓄能电站在电力系统中的调峰填谷功能,以及如何利用粒子群算法优化其调度策略。文章首先介绍了抽水蓄能电站在电力需求高峰和低谷时的不同角色,强调其对电网稳定性和经济效益的重要性。接着,结合各类电源的调峰电价机制,提出了一个以成本最低为目标的混合发电系统调峰经济调度模型。随后,引入粒子群算法作为优化工具,通过模拟自然群体行为,在解空间中搜索最优解,从而找到最佳调度方案。最后,通过MATLAB仿真验证了该模型的有效性,证明其能在保证电网稳定的同时实现成本最小化。 适合人群:从事电力系统研究、调度管理的专业人士,以及对智能调度技术和粒子群算法感兴趣的科研人员。 使用场景及目标:适用于需要优化抽水蓄能电站调度策略的研究机构和企业,旨在提高电网稳定性并降低成本。 其他说明:随着绿色能源的快速发展和智能电网的推进,抽水蓄能电站在未来将发挥更重要的作用,因此该研究对未来能源发展具有指导意义。

    毕业设计-付费阅读5.4.5 开源版-整站商业源码.zip

    毕业设计-付费阅读5.4.5 开源版-整站商业源码.zip

Global site tag (gtag.js) - Google Analytics