代码重构总结(下篇)

(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.}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值