代码重构总结(下篇)

(11) - 替换switch语句

用switch语句时,当通过增加一个新类对基于switch结构的系统进行修改时,程序员可能会忘记将其添加到现有的所有switch结构中。每次新增和删除一个类都需要修改系统中的所有switch结构,但追踪这些语句非常耗时,而且也容易出错。这是就多态性编成而言的。
01. public boolean isLeap(int year) {
02. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
03. }
04.  
05. public static int getMonthDays(int year, int month) {
06. int numberDays = 0;
07.  
08. switch (month) {
09. case 1:
10. case 3:
11. case 5:
12. case 7:
13. case 8:
14. case 10:
15. case 12:
16. numberDays = 31;
17. break;
18.  
19. case 4:
20. case 6:
21. case 9:
22. case 11:
23. numberDays = 30;
24. break;
25.  
26. case 2:
27. numberDays = isLeap(year) ? 29 28;
28. break;
29. }
30.  
31. return numberDays;
32. }
重构后
01. public boolean isLeap(int year) {
02. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
03. }
04.  
05. private int getFebruaryDays(int year) {
06. return this.isLeap(year) ? 29 28;
07. }
08.  
09. public int getMonthDays(int year, int month) {
10. int[] months = new int[] { 31this.getFebruaryDays(year), 31303130,
11. 313130313031 };
12.  
13. return months[month];
14. }

(12) - 使用对象分装参数

当一个方法参数太多时,我一般认为超过4个的时候
1. public int getRemainMinutes(int hour, int minute,
2. int fromHour, int fromMinute
3. int toHour, int toMinute) {
4. ......
重构后
1. public int getRemainMinutes(DatePart datePart) {
2. ......

谈(13) - 封装集合操作

01. public Class Group{
02.  
03. private List<User> userList = new ArrayList<User>();
04.  
05. public void setUserList(List<User> userList){
06. this.userList = userList;
07. }
08.  
09. public List<User> getUserList(){
10. return this.userList;
11. }
12. }
重构后
01. public Class Group{
02.  
03. private List<User> userList = new ArrayList<User>();
04.  
05. public void setUserList(List<User> userList){
06. this.userList = userList;
07. }
08.  
09. public List<User> getUserList(){
10. return this.userList;
11. }
12.  
13. public void addUser(User user){
14. this.getUserList().add(user);
15. user.setGroup(this);
16. }
17.  
18. public void removeUser(User user){
19. this.getUserList().remove(user);
20. user.setGroup(null);
21. }
22. }
谁都希望自己使用一个类后,操作能都在里面完成,而不用自己再去写,以后万一有变化也不用牵一动百
 

(14) - 使用委派代替继承

当子类从关系上根本不是父类的继承时
01. public class Sanitation
02. {
03. public String WashHands()
04. {
05. return "Cleaned!";
06. }
07. }
08.  
09. public class Child extends Sanitation
10. {
11.  
12. }
Child 和Sanitation (公共设施)是没有逻辑上的父子关系,因为小孩不可能是一个公共设施吧!所以我们为了完成这个功能可以考虑使用委派的方式。
01. public class Sanitation
02. {
03. public String WashHands()
04. {
05. return "Cleaned!";
06. }
07. }
08.  
09. public class Child
10. {
11. private Sanitation sanitation;
12.  
13. public Child()
14. {
15. sanitation = new Sanitation();
16. }
17.  
18. public String WashHands()
19. {
20. return sanitation.WashHands();
21. }
22. }
同理,如果反过来,委派的对象明显应该是子类,就应该改成继承
 

(15) - 面向接口编程

超过一个的类要使用某一个类中部分方法时,我们应该解开它们之间的依赖,让调用者使用接口,这很容易实现也可以降低代码的耦合性
01. public class ClassRegistration
02. {
03. public void Create() {
04. //代码
05. }
06.  
07. public void Transfer() {
08. //代码
09. }
10. }
11.  
12. public class RegistrationProcessor
13. {
14. public void ;P   rocessRegistration(ClassRegistration registration)
15. {
16. registration.Create();
17. registration.Transfer();
18. }
19. }
重构后
01. public interface IClassRegistration
02. {
03. public void Create();
04.  
05. public void Transfer();
06. }
07.  
08. public class ClassRegistration implements IClassRegistration
09. {
10. public void Create()
11. {
12. //代码
13. }
14.  
15. public void Transfer()
16. {
17. //代码
18. }
19. }
20.  
21. public class RegistrationProcessor
22. {
23. public void ;P   rocessRegistration(IClassRegistration registration)
24. {
25. registration.Create();
26. registration.Transfer();
27. }
28. }

(16) - 用策略模式代替if else和switch

好处是隔开耦合,以注入的形式实现功能,这使增加功能变得更加容易和简便,同样也增强了整个系统的稳定性和健壮性。 
但并不是所有情况都要这么改,而是从意义上符合策略模式。
01. public class ClientCode{
02. public double CalculateShipping()
03. {
04. ShippingInfo shippingInfo = new ShippingInfo();
05. return shippingInfo.CalculateShippingAmount(State.Alaska);
06. }
07. }
08.  
09. public enum State
10. {
11. Alaska,
12. NewYork,
13. Florida
14. }
15.  
16. public class ShippingInfo
17. {
18. public double CalculateShippingAmount(State shipToState)
19. {
20. if (shipToState == State.Alaska) return GetAlaskaShippingAmount();
21. else if (shipToState == State.NewYork) return GetNewYorkShippingAmount();
22. else if (shipToState == State.Florida) return GetFloridaShippingAmount();
23. else return 0d;
24. }
25.  
26. private double GetAlaskaShippingAmount()
27. {
28. return 15d;
29. }
30.  
31. private double GetNewYorkShippingAmount()
32. {
33. return 10d;
34. }
35.  
36. private double GetFloridaShippingAmount()
37. {
38. return 3d;
39. }
40. }
重构后
01. public class ClientCode
02. {
03. public IShippingInfo ShippingInfo;
04.  
05. public double CalculateShipping()
06. {
07. return ShippingInfo.CalculateShippingAmount(State.Alaska);
08. }
09. }
10.  
11. public enum State
12. {
13. Alaska,
14. NewYork,
15. Florida
16. }
17.  
18. public class ShippingInfo implements IShippingInfo
19. {
20. private Map<State, IShippingCalculation> shippingCalculations;
21.  
22. public ShippingInfo(List<IShippingCalculation> shippingList)
23. {
24. shippingCalculations = new HashMap<State, IShippingCalculation>();
25. for (IShippingCalculation calc : shippingList)
26. {
27. shippingCalculations.put(calc.state(), calc);
28. }
29. }
30.  
31. public double CalculateShippingAmount(State shipToState)
32. {
33. return shippingCalculations.get(shipToState).Calculate();
34. }
35. }
36.  
37. public interface IShippingCalculation
38. {
39. State state();
40.  
41. double Calculate();
42. }
43.  
44. public class AlaskShippingCalculation implements IShippingCalculation
45. {
46. public State State()
47. {
48. return State.Alaska;
49. }
50.  
51. public double Calculate()
52. {
53. return 15d;
54. }
55. }
56.  
57. public class NewYorkShippingCalculation implements IShippingCalculation
58. {
59. public State State()
60. {
61. return State.NewYork;
62. }
63.  
64. public double Calculate()
65. {
66. return 10d;
67. }
68. }
69.  
70. public class NewYorkShippingCalculation implements IShippingCalculation
71. {
72. public State State()
73. {
74. return State.Florida;
75. }
76.  
77. public double Calculate()
78. {
79. return 13;
80. }
81. }

(17) - 分解复杂判断

把原来复杂的条件判断等语句用尽快返回等方式简化代码
01. public interface ISecurityChecker{
02. public boolean CheckPermission(String user, String permission);
03. }
04. public class Security
05. {
06. public ISecurityChecker securityChecker;
07.  
08. public Security(ISecurityChecker securityChecker) {
09. this.securityChecker = securityChecker;
10. }
11.  
12. public boolean HasAccess(String user, String permission,  List exemptions)
13. {
14. boolean hasPermission = false;
15. if (user != null)
16. {
17. if (permission != null)
18. {
19. if (exemptions.size() == 0)
20. {
21. if (securityChecker.CheckPermission(user, permission) || exemptions.contains(permission))
22. {
23. hasPermission = true;
24. }
25. }
26. }
27. }
28. return hasPermission;
29. }
30. }
重构后
01. public interface ISecurityChecker
02. {
03. public boolean CheckPermission(String user, String permission);
04. }
05. public class Security
06. {
07. public ISecurityChecker securityChecker;
08.  
09. public Security(ISecurityChecker securityChecker) {
10. this.securityChecker = securityChecker;
11. }
12.  
13. public boolean HasAccess(String user, String permission, List exemptions)
14. {
15. if (user == null || permission == nullreturn false;
16. if (exemptions.contains(permission)) return true;
17. return securityChecker.CheckPermission(user, permission);
18. }
19. }

(18) - 契约式设计

契约式设计规定方法应该对输入和输出进行验证,这样你便可以保证你得到的数据是可以工作的,一切都是按预期进行的,如果不是按预期进行,异常或是错误就应该被返回,下面我们举的例子中,我们方法中的参数可能会值为 null 的情况,在这种情况下由于我们没有验证, NullReferenceException 异常会报出 

01. public class Customer
02. {
03. public double balance;
04.  
05. public double getBalance()
06. {
07. return balance;
08. }
09.  
10. public void setBalance(double balance)
11. {
12. this.balance = balance;
13. }
14. }
15.  
16. public class CashRegister
17. {
18. public double TotalOrder(List<Double> products, Customer customer)
19. {
20. double total = 0;
21. for (Double prise : products)
22. {
23. total += prise;
24. }
25. total += customer.getBalance();
26. return total;
27. }
28. }
重构后
01. public class CashRegister
02. {
03. public double TotalOrder(List<Double> products, Customer customer)
04. {
05. if (customer == nullthrow new IllegalArgumentException("Customer cannot be null");
06.  
07. if (products == null || products.isEmpty()) throw new IllegalArgumentException("Must have at least one product to total");
08.  
09. double total = 0;
10. for (Double prise : products)
11. {
12. total += prise;
13. }
14. total += customer.getBalance();
15. return total;
16. }
17. }

(19) - 除去上帝类

当一个类职责太大,方法实在太多,可以考虑细化成多个类
01. public class CustomerService
02. {
03. public double calculateOrderDiscount()
04. {
05. //实现
06. }
07.  
08. public boolean customerIsValid()
09. {
10. //实现
11. }
12.  
13. public boolean register()
14. {
15. //实现
16. }
17.  
18. public boolean forgotPassword()
19. {
20. //实现
21. }
22. }
重构后
01. public class CustomerOrderService
02. {
03. public double calculateOrderDiscount()
04. {
05. //实现
06. }
07.  
08. public boolean customerIsValid()
09. {
10. //实现
11. }
12. }
13.  
14. public class CustomerRegistrationService
15. {
16. public boolean register()
17. {
18. //实现
19. }
20.  
21. public boolean forgotPassword()
22. {
23. //实现
24. }
25. }

(20) - 尽快返回

当条件判断对性能消耗较大时,这种的写法得尽可能避免
01. public boolean test()
02. {
03. boolean result;
04. if (条件判断) result = true;
05. else (条件判断) result = false;
06. else(条件判断) result = true;
07. else(条件判断) result = false;
08. else(条件判断) result = true;
09. else(条件判断) result = false;
10. else result = true;
11. return result;
12. }
重构后
01. public boolean test()
02. {
03. if (条件判断) return true;
04. else (条件判断) return false;
05. else(条件判断) return true;
06. else(条件判断) return false;
07. else(条件判断) return true;
08. else(条件判断) return false;
09. else return true;
10. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值