提取方法对象

概念:本文中的“提取方法对象”是指当你发现一个方法中存在过多的局部变量时,你可以通过使用“提取方法对象”重构来引入一些方法,每个方法完成任务的一个步骤,这样可以使得程序变得更具有可读性。

正文:如下代码所示,Order 类中的Calculate方法要完成很多功能,在之前我们用“提取方法”来进行重构,现在我们采取“提取方法对象”来完成重构。

using System.Collections.Generic;

namespace LosTechies.DaysOfRefactoring.ExtractMethodObject.Before
{
    public class OrderLineItem
    {
        public decimal Price { get; private set; }
    }

    public class Order
    {
        private IList<OrderLineItem> OrderLineItems { get; set; }
        private IList<decimal> Discounts { get; set; }
        private decimal Tax { get; set; }

        public decimal Calculate()
        {
            decimal subTotal = 0m;

            // Total up line items
            foreach (OrderLineItem lineItem in OrderLineItems)
            {
                subTotal += lineItem.Price;
            }

            // Subtract Discounts
            foreach (decimal discount in Discounts)
                subTotal -= discount;

            // Calculate Tax
            decimal tax = subTotal * Tax;

            // Calculate GrandTotal
            decimal grandTotal = subTotal + tax;

            return grandTotal;
        }
    }
}

正如下代码所示,我们引入了OrderCalculator类,该类实现了所有的计算方法,Order类将自身传递给 OrderCalculator类并调用Calculate方法完成计算过程。

using System.Collections.Generic;

namespace LosTechies.DaysOfRefactoring.ExtractMethodObject.After
{
    public class OrderLineItem
    {
        public decimal Price { get; private set; }
    }

    public class Order
    {
        public IEnumerable<OrderLineItem> OrderLineItems { get; private set; }
        public IEnumerable<decimal> Discounts { get; private set; }
        public decimal Tax { get; private set; }

        public decimal Calculate()
        {
            return new OrderCalculator(this).Calculate();
        }
    }

    public class OrderCalculator
    {
        private decimal SubTotal { get; set; }
        private IEnumerable<OrderLineItem> OrderLineItems { get; set; }
        private IEnumerable<decimal> Discounts { get; set; }
        private decimal Tax { get; set; }

        public OrderCalculator(Order order)
        {
            OrderLineItems = order.OrderLineItems;
            Discounts = order.Discounts;
            Tax = order.Tax;
        }

        public decimal Calculate()
        {
            CalculateSubTotal();

            SubtractDiscounts();

            CalculateTax();

            return SubTotal;
        }

        private void CalculateSubTotal()
        {
            // Total up line items
            foreach (OrderLineItem lineItem in OrderLineItems)
                SubTotal += lineItem.Price;
        }

        private void SubtractDiscounts()
        {
            // Subtract Discounts
            foreach (decimal discount in Discounts)
                SubTotal -= discount;
        }

        private void CalculateTax()
        {
            // Calculate Tax
            SubTotal += SubTotal * Tax;
        }
    }
}

总结:本文的重构方法在有的时候还是比较有用,但这样会造成字段的增加,同时也会带来一些维护的不便,它和“提取方法”最大的区别就是一个通过方法返回需要的数据,另一个则是通过字段来存储方法的结果值,所以在很大程度上我们都会选择“提取方法”。

版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。

时间: 2024-10-10 18:47:06

提取方法对象的相关文章

小酌重构系列[2]&mdash;&mdash;提取方法、提取方法对象

前言 "艺术源于生活"--代码也源于生活,你在生活中的一些行为习惯,可能会恰如其分地体现在代码中.当实现较为复杂的功能时,由于它包含一系列的逻辑,我们倾向于编写一个"大方法"来实现.为了使项目便于维护,以及增强代码的可读性,我们有必要对"大方法"的逻辑进行整理,并提取出分散的"小方法".这就是本文要讲的两种重构策略:提取方法.提取方法对象. 如何快速地找到想读的书? 在生活中,我是一个比较随意的人,平时也买了不少书去看.我的书

重构13-Extract Method Object(提取方法对象)

重构来自于Martin Fowler的重构目录.你可以在这里找到包含简介的原始文章. 在我看来,这是一个比较罕见的重构,但有时却终能派上用场.当你尝试进行提取方法的重构时,需要引入大量的方法.在一个方法中使用众多的本地变量有时会使代码变得丑陋.因此最好使用提取方法对象这个重构,将执行任务的逻辑分开 public class OrderLineItem { public Double Price;}public class Order { private List<OrderLineItem>

[Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数arguments对象.它是一个类数组对象,并不是一个标准的数组,所以无法使用数组原型中的方法,因此无法使用arguments.forEach这样的形式来遍历每一个参数.这里我们必须使用call方法来对使用forEach方法. function highlight(){ [].forEach.call(argume

C#重构经典全面汇总

C#重构经典全面汇总 1.  封装集合 概念:本文所讲的封装集合就是把集合进行封装,仅仅提供调用端须要的接口. 正文:在非常多时候,我们都不希望把一些不必要的操作暴露给调用端,仅仅须要给它所须要的操作或数据即可,那么做法就是封装.这个重构在微软的代码库也常常遇到. 比方最经典的属性对字段的封装就是一个非常好的样例,那么以下我们将看到对集合的封装.例如以下代码所看到的,调用端仅仅须要一个集合的信息,而我们则提供了一个IList的集合.大家都知道IList具有对集合的全部操作,所以这会带来非常多隐患

小酌重构系列[4]&mdash;&mdash;分解方法

概述 "分解方法"的思想和前面讲到的"提取方法"."提取方法对象"基本一致.它是将较大个体的方法不断的拆分,让每个"方法"做单一的事情,从而提高每个方法的可读性和可维护性.分解方法可以看做是"提取方法"的递归版本,它是对方法反复提炼的一种重构策略. 分解方法 下图表示了这个重构策略,第1次提炼和第2次提炼都采用了"提取方法"这个策略. 何时分解方法? "分解方法"最终

[Effective JavaScript 笔记]第5章:数组和字典--个人总结

前言 这节里其实一直都在讨论对象这个在js中的万能的数据结构.对象可以表式为多种的形式,表示为字典和数组之间的区别.更多的我觉得这章讨论多的是一些对应实现功能的相关操作,有可能出现的bug以及如何避免来修复这些bug.比如下面会说到的for...in枚举属性的操作,可能因为对原型的一些操作,最终造成数据对象的操作的破坏.对于属性顺序有要求的如何处理,对类数组如何处理等.下面再一起一条一条回顾一下,这章里的主要内容.我觉得没必要讲的会一语带过,相比前面的几章,个人觉得这章的内容重点很少,注意几点就

如何才能熟练使用 Android Studio?

推荐购买<精通AndroidStudio> 编辑推荐 资深Android开发工程师根据新版Android Studio 2.2 精心打造的<精通AndroidStudio>.详细介绍了 Android Studio 实用的功能与技巧,非常全面.系统.专业.实例丰富. 内容简介 本书以通俗易懂的语言全面系统地介绍了Android Studio实用工具和操作技巧,场景明确,步骤清晰,图文结合.全书共16章.第1章对Android Studio做概要的介绍,从特性.界面.工具.功能到环境

分解方法

分解方法 概述 “分解方法”的思想和前面讲到的“提取方法”.“提取方法对象”基本一致.它是将较大个体的方法不断的拆分,让每个“方法”做单一的事情,从而提高每个方法的可读性和可维护性.分解方法可以看做是“提取方法”的递归版本,它是对方法反复提炼的一种重构策略. 分解方法 下图表示了这个重构策略,第1次提炼和第2次提炼都采用了“提取方法”这个策略. 何时分解方法? “分解方法”最终可以让方法的可读性极大地增强,通常我们可以依据以下几点来辨别方法是否需要分解: 1. 每个方法应该只做一件事情(对事情的

编写高质量JS代码的68个有效方法(十一)

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD