
《重构》
重构笔记
gqltt
这个作者很懒,什么都没留下…
展开
-
Replace Delegation with Inheritance(以继承取代委托)
两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数重构:让委托类继承受托类原创 2021-09-07 19:56:42 · 215 阅读 · 0 评论 -
Replace Inheritance with Delegation(以委托取代继承)
某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据重构:在子类中新建一个字段用来保存超类,调整子类函数,令它改而委托超类,然后去掉两者的继承关系原创 2021-09-07 19:52:33 · 303 阅读 · 0 评论 -
Form Template Method(塑造模板函数)
有一些子类,其中相应的某些函数以相同顺序执行类似的操作,但各个操作的细节有不同重构:将这些操作分别放进独立函数中,并保持它们都有相同的签名,然后将原函数上移至超类原创 2021-09-07 19:49:10 · 304 阅读 · 0 评论 -
Collapse Hierarchy(折叠继承体系)
超类和子类之间无太大区别重构:将它们合为一体原创 2021-09-07 19:34:11 · 607 阅读 · 0 评论 -
Extract Interface(提炼接口)
两个类的接口有部分相同重构:将相同的子集提炼到一个独立接口中原创 2021-09-07 19:31:37 · 402 阅读 · 0 评论 -
Extract Superclass(提炼超类)
两个类有相识特性重构:为这两个类建立一个超类,将相同特性搬移到超类原创 2021-09-07 19:22:55 · 639 阅读 · 0 评论 -
Extract Subclass(提炼子类)
类中的某些特性只被某些实例用到重构:新建一个子类,将一部分特性搬移到子类中原创 2021-09-07 19:19:19 · 149 阅读 · 0 评论 -
Pull Up Constructor Body(构造函数本体上移)
各个子类中拥有一些构造函数,它们的本体几乎完全一致public class Manager extends Employee { public Manager(String name, String id, int grade) { this.name = name; this.id = id; this.grade = grade; }}重构:在超类中新建一个构造函数,并在子类构造函数中调用它 public Manager(String name, String id,原创 2021-09-07 19:15:20 · 271 阅读 · 0 评论 -
Pull Up Method(函数上移)
有些函数,在各个子类中产生完全相同的结果重构:将该函数移至超类原创 2021-09-07 19:09:04 · 191 阅读 · 0 评论 -
Pull Up Field(字段上移)
两个子类拥有形同的字段重构:将该字段移至超类原创 2021-09-06 14:21:17 · 333 阅读 · 0 评论 -
Replace Exception with Test(以测试取代异常)
面对一个可以预先检查的条件,却抛出了一个异常public double getValueForPeriod(int periodNumber) { try { return values[periodNumber]; } catch (ArrayIndexOutOfBoundsException e) { return 0; }}重构:调用函数之前先做检查public double getValueForPeriod(int periodNumber) { if (peri原创 2021-09-06 12:01:07 · 238 阅读 · 0 评论 -
Replace Error Code with Exception(以异常取代错误码)
某个函数返回一个特定的代码,用来表示某种错误情况public int withdraw(int amount) { if (amount > balance) { return -1; } else { balance -= amount; return 0; }}重构:改用异常public int withdraw(int amount) { if (amount > balance) { throw new BalanceException("余额不原创 2021-09-06 11:56:15 · 580 阅读 · 0 评论 -
Encapsulate Downcast(封装向下转型)
某个函数返回的对象,需要由函数调用者执行向下转型(downcast)public Object lastReading() { return readings.lastElement();}重构:将向下转型动作移动到函数中。public Reading lastReading() { return (Reading) readings.lastElement();}...原创 2021-09-06 11:50:43 · 207 阅读 · 0 评论 -
Introduce Parameter Object(引入参数对象)
某些参数总是很自然地同时出现重构:以一个对象取代这些参数原创 2021-09-06 11:37:40 · 349 阅读 · 0 评论 -
Replace Parameter with Methods(以函数取代参数)
对象调用某个函数,并将其结果传递给另一个函数int basePrice = quantity * itemPrice;double discountLevel = getDiscountLevel();double finalPrice = discountPrice(basePrice, discountLevel);重构:让参数接受者移除该项参数,并直接调用该函数int basePrice = quantity * itemPrice;double finalPrice = dis原创 2021-09-06 11:32:34 · 307 阅读 · 0 评论 -
Preserve Whole Object(保持对象完整)
从某个对象中取出若干值,将它们作为某一次函数调用的参数int low = daysTempRange().getLow();int height = daysTempRange().getHigh();withinPlan = plan.withinRange(low, high);重构:改为传递整个对象withinPlan = plan.withinRange(daysTempRange());...原创 2021-09-06 10:50:25 · 233 阅读 · 0 评论 -
Replace Parameter with Explicit Methods(以明确函数取代参数)
函数的行为,完全取决于参数值public void setValue(final String name, final int value) { if ("height".equals(name)) { this.height = value; return; } if ("width".equals(name)) { this.width = value; return; } Assert.shouldNeverReachHere();}重构:针对该参数的每一原创 2021-09-06 10:44:55 · 426 阅读 · 0 评论 -
Parameterize Method(令函数携带参数)
若干函数做了类似的工作,但在函数体中却包含了不同的值重构:建立单一函数,以参数表达那些不同的值。原创 2021-09-06 10:38:32 · 181 阅读 · 0 评论 -
Separate Query from Modifier(分离查询和修改)
某个函数既返回对象状态值,又修改对象状态重构:建立两个不同的函数,其中一个负责查询,另一个负责修改动机 如果某个函数只是向你提供一个值,没有任何看得到的副作用,那么这是个很有价值的东西。你可以任意调用这个函数,也可以把invoke搬到函数的其他地方。 明确表现出“有副作用”与“无副作用”两种函数之间的差异,是个很好的想法。下面是一条好规则:任何有返回值的函数,都不应该有看得到的副作用。 什么是“看得到的副作用”?有一种常见的优化方法:将查询所得结果缓存于某个字段...原创 2021-09-06 10:25:52 · 247 阅读 · 0 评论 -
Introduce Null Object(引入Null 对象)
一而再,再而三地检查对象是否nullpublic class Site { private Customer customer; public Customer getCustomer() { return customer; }}public class Customer { private String name; private BillingPlan plan; private PaymentHistory history; public Strin原创 2021-09-03 22:02:22 · 399 阅读 · 0 评论 -
Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件表达式)
函数中的条件逻辑使人难以看清正常的执行路径double getPayAmount() { double result; if (isDead) { result = deadAmount(); } else { if (isSeparated) { result = separatedAmount(); } else { if (isRetired) { result = retiredAmount(); } else { result = norm原创 2021-09-03 17:47:03 · 188 阅读 · 0 评论 -
Consolidate Duplicate Conditional Fragments(合并重复的条件片段)
在条件表达式的每个分支上有相同的一段代码if (isSpecialDeal()) { total = price * 0.95; send();} else { total = price * 0.98; send();}重构:将这段重复代码搬移到条件表达式之外if (isSpecialDeal()) { total = price * 0.95;} else { total = price * 0.98;}send();...原创 2021-09-03 17:04:19 · 349 阅读 · 0 评论 -
Consolidate Conditional Expression(合并条件表达式)
有一系列条件测试,都得到相同结果private double disabilityAmount() { if (seniority < 2) return 0; if (monthsDisabled > 2) return 0; if (isPartTime) return 0; // ...}重构:将这些条件测试合并为一个条件表达式,并提炼为一个独立函数private double disabilityAmount() { if (isNotEligibleForD原创 2021-09-03 16:58:34 · 287 阅读 · 0 评论 -
Decompose Conditional(分解条件表达式)
有一个复杂的 if-else 语句if (date.before(SUMMER_START) || date.after(SUMMER_END)) { charge = quantity * winterRate + winterServiceCharge;} else { charge = quantity * summerRate;}重构:从if-else 中分别提炼出独立函数if (notSummer(date)) { charge = winterCharge(quant.原创 2021-09-03 16:51:35 · 149 阅读 · 0 评论 -
Replace Type Code with State/Strategy(以State/Strategy取代类型码)
有一个类型码,它会影响类的行为,但你无法通过继承消除它public class Employee { static final int ENGINNER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; private int type; // 月薪. private int montylySalary; // 佣金. private int commission; // 奖金. p.原创 2021-09-02 20:57:31 · 307 阅读 · 0 评论 -
Replace Type Code with Subclasses(以子类取代类型码)
有一个不可变的类型码,它会影响类的行为public class Employee { static final int ENGINNER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; private int type; public Employee(int type) { this.type = type; } public int getType() { return type;原创 2021-09-02 20:09:51 · 248 阅读 · 0 评论 -
Replace Type Code with Class(以类取代类型码)
类之中有一个数值类型码,但它不影响类的行为public class Person { /** * O * A * B * AB */ private int bloodGroup;}重构:用一个新的类替换该数值类型码public class Person { private BloodGroup bloodGroup;}public enum BloodGroup { O, A, B, AB}...原创 2021-09-02 19:39:30 · 392 阅读 · 0 评论 -
Encapsulate Collection(封装集合)
函数直接返回了一个集合public class Person { private Set<Course> courses; public Set<Course> getCourses() { return courses; } public void setCourses(final Set<Course> courses) { this.courses = courses; }}重构:让这个函数返回该集合的一个只读副本,并在这个类中原创 2021-09-02 19:26:00 · 299 阅读 · 0 评论 -
Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
两个类都需要使用对方特性,但其间只有一个单向连接重构:添加一个反向指针,并使修改函数能够同时更新两条连接由哪个类负责控制关联关系。建议单个类来操控,因为这样就可以将所有处理关联关系的逻辑安置于一地。 1、如果两者都是引用对象,而期间的关联是“一对多”关系,那么就由“拥有单一引用”的那一方承担“控制者”角色。 2、如果某个对象是组成另一个对象的部件,那么由后者(整体)负责控制关联关系。 3、如果两者都是引用对象,而期间的关联是“多对多”关系,那么随便哪个对象控制关联关系...原创 2021-09-02 16:48:52 · 389 阅读 · 0 评论 -
Duplicate Observed Data(复制“被监视数据”)
一些领域数据置身于GUI控件中,而领域函数需要访问这些数据重构:将该数据复制到一个领域对象中。建立一个Observer 模式,可以同步领域对象和GUI 对象内的重复数据。动机 一个分层良好的系统,应该将处理用户界面和处理业务逻辑的代码分开。之所以这样做,有以下2点原因: 1、可能需要使用不同的用户界面来表现相同的业务逻辑,如果同时承担两种责任,用户界面会变得过分复杂; 2、与GUI 隔离之后,领域对象的维护和演化都会更容易。 ...原创 2021-08-31 21:17:27 · 290 阅读 · 0 评论 -
Replace Array with Object(以对象取代数组)
有一个数组,其中的元素各自代表不同的东西String[] row = new String[3];row[0] = "Liverpool";row[1] = "15";重构:以对象替换数组。对于数组中的每个元素,以一个字段来表示Performance row = new Performance();row.setName("Liverpool");row.setWins("15");...原创 2021-08-31 20:48:01 · 142 阅读 · 0 评论 -
Change Value to Reference(将值对象改为引用对象)
从一个类衍生出许多彼此相等的实例,希望将他们替换为同一个对象将这个值对象变成引用对象。动机 在许多系统中,你都可以为对象做一个有用的分类:引用对象和值对象。前者就像“客户”、“账户”这样的东西,每个对象都代表真实世界中的一个实物,你可以直接使用==检查两个对象是否相等。后者则是像“日期”、“钱”这样的东西,它们完全由其所含的数据值来定义,你并不在意副本的存在,当然,你也需要知道两个对象是否相等,所以你需要覆写equals() 和 hashCode()。...原创 2021-08-31 20:42:45 · 298 阅读 · 0 评论 -
Replace Data Value with Object(以对象取代数据值)
有一个数据项,需要与其他数据和行为一起使用才有意义将数据项变成对象。动机 开发初期,你往往决定以简单的数据项表示简单的情况。但是,随着开发的进行,你可能会发现,这些简单数据项不再那么简单了。比如说,一开始你可能会用一个字符串来表示“电话号码”概念,但是随后你就会发现,电话号码需要“格式化”、“抽取区号”之类的特殊行为。...原创 2021-08-31 20:23:05 · 257 阅读 · 0 评论 -
Self Encapsulate Field(自封装字段)
直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙private int low;private int high;boolean includes(int arg) { return arg >= low && arg <= high;}重构:为这个字段建立get/set函数,并以这些函数访问字段private int low;private int high;public int getLow() { return low;}publ原创 2021-08-26 21:35:32 · 271 阅读 · 0 评论 -
Introduce Foreign Method(引入外加函数)
需要为提供服务的类增加一个函数,但你无法修改这个类Date newStart = new Date(previousEnd.getYear(), previousEnd.getMonth(), previousEnd.getDate() + 1);重构:在客户类中建立一个函数Date newStart = nextDay(previousEnd); private static Date nextDay(Date arg) { return new Date(arg.ge原创 2021-08-26 20:55:38 · 190 阅读 · 0 评论 -
Hide Delegate(隐藏“委托关系”)
通过一个委托类来调用另一个对象重构:在服务类上建立客户所需的所有函数,用以隐藏委托关系。原创 2021-08-26 20:46:34 · 236 阅读 · 0 评论 -
Substitute Algorithm(替换算法)
把某个算法替换成另一个更清晰的算法public String foundPerson(String[] people) { for(int i=0; i<people.length; i++) { if (people[i].equals("Don")) { return "Don"; } if (people[i].equals("John")) { return "John"; } if (people[i].equals("Kent")) { ret原创 2021-08-24 21:36:37 · 293 阅读 · 0 评论 -
Replace Method with Method Object(以函数对象取代函数)
在一个大型函数中,由于局部变量的使用导致无法采用ExtractMethodclass Order... double price() { double primaryBasePrice; double secondaryBasePrice; double teriaryBasePrice; // long computation. .... }}重构:将这个函数放进一个单独对象中,局部变量成了对象内的字段...原创 2021-08-24 20:53:38 · 238 阅读 · 0 评论 -
Remove Assignments to Parameters(移除对参数的赋值)
对入参进行赋值int discount(int inputVal, int quantity, int yearToDate) { if (inputVal > 50) { inputVal -= 2; }}重构:用一个临时变量取代该参数int discount(int inputVal, int quantity, int yearToDate) { int result = inputVal; if (inputVal > 50) { result -= 2原创 2021-08-24 20:28:18 · 188 阅读 · 0 评论 -
Split Temporary Variable(分解临时变量)
某个变量被赋值超过一次,它既不是循环变量,也不被用于汇总结果double temp = 2 * (height + width);System.out.println(temp);temp = height * width;System.out.println(temp);重构后final double perimeter = 2 * (height + width);System.out.println(perimeter);final double area = height原创 2021-08-24 20:23:12 · 230 阅读 · 0 评论