应用内部类完成"Replace Method with Method Object"(以函数对象取代函数)重构
使用内部类完成"Replace Method with Method Object"(以函数对象取代函数)重构
“Replace Method with Method Object”(以函数对象取代函数)是一种重新组织函数(也就是Java中的方法,在本文中函数和方法这两个词表示的意思相同)的重构方法。其做法是将函数放进一个单独的对象当中,使用这个单独对象的值域(filed)来替代原函数中的局部变量。这样做的好处是对于一个拥有较多较复杂的局部变量的函数来说,进行“extract method”重构变得较为容易。
偷懒,直接使用“重构——改善既有代码设计【Martin Flower】”一书中这个没有什么逻辑性的例子(有一些改动):
代码使用JUnit进行单元测试,在测试方法中调用时将ReplaceMethodWithMethodObject对象本身的引用传入Gamma对象的gamma方法。
其实这里可以使用内部类来进行该项重构,代码如下:
使用内部类进行“Replace Method with Method Object”重构带来两点好处:一是调用重构后的对象的函数时不用再传入当前对象的引用(因为内部类对象自动持有其外围类对象的引用);二是重构函数中调用的原对象中的其他函数可以不用public(请对比两段代码,注意delta()函数的访问修饰符),因为在内部类中可以访问到其外围类的任何成员(包括private的方法)。
“Replace Method with Method Object”(以函数对象取代函数)是一种重新组织函数(也就是Java中的方法,在本文中函数和方法这两个词表示的意思相同)的重构方法。其做法是将函数放进一个单独的对象当中,使用这个单独对象的值域(filed)来替代原函数中的局部变量。这样做的好处是对于一个拥有较多较复杂的局部变量的函数来说,进行“extract method”重构变得较为容易。
偷懒,直接使用“重构——改善既有代码设计【Martin Flower】”一书中这个没有什么逻辑性的例子(有一些改动):
public class ReplaceMethodWithMethodObject extends TestCase { int gamma(int inputVal, int quantity, int yearToDate) { int importantValue1 = (inputVal * quantity) + delta(); int importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; return importantValue3 - 2 * importantValue1; } public int delta() { return 5; } public void testGamma() { assertEquals(875, new Gamma(this, 5, 6, 7).gamma()); } } //outer class method object class Gamma { private ReplaceMethodWithMethodObject rmwmb; private int inputVal; private int quantity; private int yearToDate; public Gamma(ReplaceMethodWithMethodObject rmwmb ,int inputVal, int quantity, int yearToDate) { this.rmwmb = rmwmb; this.inputVal = inputVal; this.quantity = quantity; this.yearToDate = yearToDate; } int gamma() { int importantValue1 = (inputVal * quantity) + rmwmb.delta(); int importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; return importantValue3 - 2 * importantValue1; } }
代码使用JUnit进行单元测试,在测试方法中调用时将ReplaceMethodWithMethodObject对象本身的引用传入Gamma对象的gamma方法。
其实这里可以使用内部类来进行该项重构,代码如下:
public class ReplaceMethodWithMethodObject extends TestCase { int gamma(int inputVal, int quantity, int yearToDate) { int importantValue1 = (inputVal * quantity) + delta(); int importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; return importantValue3 - 2 * importantValue1; } private int delta() { return 5; } /* * replace method with inner class method object(could be better than outer class!) */ class Gamma { private int inputVal; private int quantity; private int yearToDate; public Gamma(int inputVal, int quantity, int yearToDate) { this.inputVal = inputVal; this.quantity = quantity; this.yearToDate = yearToDate; } int gamma() { int importantValue1 = (inputVal * quantity) + delta(); int importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; return importantValue3 - 2 * importantValue1; } } public void testGamma() { assertEquals(875, new Gamma(5, 6, 7).gamma()); } }
使用内部类进行“Replace Method with Method Object”重构带来两点好处:一是调用重构后的对象的函数时不用再传入当前对象的引用(因为内部类对象自动持有其外围类对象的引用);二是重构函数中调用的原对象中的其他函数可以不用public(请对比两段代码,注意delta()函数的访问修饰符),因为在内部类中可以访问到其外围类的任何成员(包括private的方法)。