• IDEA代码重构技巧--拆分类


    IDEA代码重构技巧--目录页

    1. 小声哔哔

        方法会腐化,同样,对象类也会腐化,不同人对业务理解的不同导致一个对象类可能被添加了很多不属于他的属性,这时就产生了代码的坏味道,此时我们需要将对象类拆分。

        示例代码:

    1. /**
    2. * @author: Coline
    3. * @ClassName: AirportCheckIn
    4. * @Date: 2022/8/20 23:28
    5. * @Description: 机场值机--只是抽取了部分作为案例,不做实际值机流程参考
    6. * 1.登机牌
    7. * 2.托运行李
    8. * 3.购买附加服务
    9. */
    10. public class AirportCheckIn {
    11. /**
    12. * 登机牌
    13. * 1. 姓名
    14. * 2. 身份证号
    15. * 3. 航班号
    16. * 4. 出发地
    17. * 5. 到达地
    18. */
    19. private String name;
    20. private String idCard;
    21. private String flightNumber;
    22. private String fromAddress;
    23. private String toAddress;
    24. /**
    25. * 托运行李:
    26. * 1. 行李重量
    27. * 2. 托运费用
    28. * 3. 是否办理托运
    29. */
    30. private double luggageWeight;
    31. private double freight;
    32. private boolean isConsignment;
    33. /**
    34. * 购买增值服务
    35. * 1. 是否购买保险服务
    36. * 2. 保险价格
    37. * 3. 是否商务舱升舱
    38. * 4. 升舱价格
    39. */
    40. private boolean isInsurance;
    41. private double insurancePrice;
    42. private boolean isBusinessUpgrade;
    43. private double upgradePrice;
    44. public AirportCheckIn(String name, String idCard, String flightNumber, String fromAddress, String toAddress
    45. , double luggageWeight, double freight, boolean isConsignment, boolean isInsurance
    46. , double insurancePrice, boolean isBusinessUpgrade, double upgradePrice) {
    47. this.name = isEmpty(name, "name can not be null");
    48. this.idCard = idCard;
    49. this.flightNumber = flightNumber;
    50. this.fromAddress = fromAddress;
    51. this.toAddress = toAddress;
    52. this.luggageWeight = luggageWeight;
    53. this.freight = freight;
    54. this.isConsignment = isConsignment;
    55. this.isInsurance = isInsurance;
    56. this.insurancePrice = insurancePrice;
    57. this.isBusinessUpgrade = isBusinessUpgrade;
    58. this.upgradePrice = upgradePrice;
    59. }
    60. public String getName() {
    61. return name;
    62. }
    63. public String getIdCard() {
    64. return idCard;
    65. }
    66. public String getFlightNumber() {
    67. return flightNumber;
    68. }
    69. public String getFromAddress() {
    70. return fromAddress;
    71. }
    72. public String getToAddress() {
    73. return toAddress;
    74. }
    75. public double getLuggageWeight() {
    76. return luggageWeight;
    77. }
    78. public double getFreight() {
    79. return freight;
    80. }
    81. public boolean isConsignment() {
    82. return isConsignment;
    83. }
    84. public boolean isInsurance() {
    85. return isInsurance;
    86. }
    87. public double getInsurancePrice() {
    88. return insurancePrice;
    89. }
    90. public boolean isBusinessUpgrade() {
    91. return isBusinessUpgrade;
    92. }
    93. public double getUpgradePrice() {
    94. return upgradePrice;
    95. }
    96. public static String isEmpty(String input, String errMessage) {
    97. if (input == null) {
    98. throw new IllegalArgumentException(errMessage);
    99. }
    100. return input;
    101. }
    102. }

    2. 拆分类

        关注示例代码,我们发现其实可以将属性拆分到三个类:
        1. 登机牌信息
        2. 行李托运
        3. 增值服务
        拆分类我们要遵循一个原则,保留旧的,创建新的,切换新的,删除旧的,以此来减少出错的可能。

    •  步骤一:保留旧的,创建新的。选中构造方法中的修改代码,键入Alt+Ctrl+M 抽取方法。

    输入方法名,例如:AirportCheckIn

    •  步骤二:将参数抽象成新的类。选中方法,键入Shift+Ctrl+Alt+t,选择Introduct Parameter Object

        填入类名,选择创建内部类和要抽取的属性

        点击Refactor后就会创建内部内,创建完成后就会生成内部类如下图。

    • 步骤三: 选择抽取出的参数,Alt+回车 创建参数

    • 步骤四:添加this。因为后面要做内联替换,所以需要将=号后面的替换后参数前加上this。

        如果类似于下面这种不能直接this的

        选中参数,Ctrl+Alt+V抽取参数

        然后将对应的参数剪切复制到内部类的构造函数中

     然后将原有调用点的String name改成this.name

    • 步骤五:旧的方法调用替换

    • 步骤六:对参数内联替换。首先选中待替换参数,键入Alt+回车,选择Make final,将参数设置为final的。

        选择参数,键入Ctrl+Alt +n

        内联替换完成后关注之前调用的地方发生了改变。

        依次将其他参数都设置为final,然后内联替换

    •  步骤七:将内部类移到预期位置。选择内部类,键入F6

         输入预期的包路径,这里可以手动输入,没有目标包的话会自动创建

    • 步骤八:对旧的外部调用方法做内联替换。选择旧的被调用的方法,键入Ctrl+Alt+n内联

    • 步骤九:去中间者。可以发现内联替换后还是存在中间者,类似下图

        点击参数 ,例如图中的boardingPass,键入Shift+Ctrl+Alt+t,选择Remove Middleman

        点击Refactor后发现效果是会删除本类中中间存在的get方法,然后可以选择性的创建boardingPass的get方法,选中参数,键入Alt+INS

     最终结果我们可以生成4个类。AirportCheckIn,ValueAdd,BoardingPass,Baggage

    1. /**
    2. * @author: Coline
    3. * @ClassName: Baggage
    4. * @Date: 2022/8/23 23:46
    5. * @Description: 行李托运
    6. */
    7. public class Baggage {
    8. private final double luggageWeight;
    9. private final double freight;
    10. private final boolean isConsignment;
    11. public Baggage(double luggageWeight, double freight, boolean isConsignment) {
    12. this.luggageWeight = luggageWeight;
    13. this.freight = freight;
    14. this.isConsignment = isConsignment;
    15. }
    16. public double getLuggageWeight() {
    17. return luggageWeight;
    18. }
    19. public double getFreight() {
    20. return freight;
    21. }
    22. public boolean isConsignment() {
    23. return isConsignment;
    24. }
    25. }

    1. import com.coline.actual.AirportCheckIn;
    2. /**
    3. * @author: Coline
    4. * @ClassName: BoardingPass
    5. * @Date: 2022/8/23 23:21
    6. * @Description: 登机牌
    7. */
    8. public class BoardingPass {
    9. private final String name;
    10. private final String idCard;
    11. private final String flightNumber;
    12. private final String fromAddress;
    13. private final String toAddress;
    14. public BoardingPass(String name, String idCard, String flightNumber, String fromAddress, String toAddress) {
    15. this.name = AirportCheckIn.isEmpty(name, "name can not be null");
    16. this.idCard = idCard;
    17. this.flightNumber = flightNumber;
    18. this.fromAddress = fromAddress;
    19. this.toAddress = toAddress;
    20. }
    21. public String getName() {
    22. return name;
    23. }
    24. public String getIdCard() {
    25. return idCard;
    26. }
    27. public String getFlightNumber() {
    28. return flightNumber;
    29. }
    30. public String getFromAddress() {
    31. return fromAddress;
    32. }
    33. public String getToAddress() {
    34. return toAddress;
    35. }
    36. }
    1. /**
    2. * @author: Coline
    3. * @ClassName: ValueAdd
    4. * @Date: 2022/8/23 23:51
    5. * @Description: 增值服务
    6. */
    7. public class ValueAdd {
    8. private final boolean isInsurance;
    9. private final double insurancePrice;
    10. private final boolean isBusinessUpgrade;
    11. private final double upgradePrice;
    12. public ValueAdd(boolean isInsurance, double insurancePrice, boolean isBusinessUpgrade, double upgradePrice) {
    13. this.isInsurance = isInsurance;
    14. this.insurancePrice = insurancePrice;
    15. this.isBusinessUpgrade = isBusinessUpgrade;
    16. this.upgradePrice = upgradePrice;
    17. }
    18. public boolean isInsurance() {
    19. return isInsurance;
    20. }
    21. public double getInsurancePrice() {
    22. return insurancePrice;
    23. }
    24. public boolean isBusinessUpgrade() {
    25. return isBusinessUpgrade;
    26. }
    27. public double getUpgradePrice() {
    28. return upgradePrice;
    29. }
    30. }
    1. import com.coline.actual.model.Baggage;
    2. import com.coline.actual.model.BoardingPass;
    3. import com.coline.actual.model.ValueAdd;
    4. /**
    5. * @author: Coline
    6. * @ClassName: AirportCheckIn
    7. * @Date: 2022/8/20 23:28
    8. * @Description: 机场值机--只是抽取了部分作为案例,不做实际值机流程参考
    9. * 1.登机牌
    10. * 2.托运行李
    11. * 3.购买附加服务
    12. */
    13. public class AirportCheckIn {
    14. private BoardingPass boardingPass;
    15. private Baggage baggage;
    16. private ValueAdd valueAdd;
    17. public AirportCheckIn(BoardingPass boardingPass, Baggage baggage, ValueAdd valueAdd) {
    18. this.boardingPass = boardingPass;
    19. this.baggage = baggage;
    20. this.valueAdd = valueAdd;
    21. }
    22. public static String isEmpty(String input, String errMessage) {
    23. if (input == null) {
    24. throw new IllegalArgumentException(errMessage);
    25. }
    26. return input;
    27. }
    28. public BoardingPass getBoardingPass() {
    29. return boardingPass;
    30. }
    31. public void setBoardingPass(BoardingPass boardingPass) {
    32. this.boardingPass = boardingPass;
    33. }
    34. public Baggage getBaggage() {
    35. return baggage;
    36. }
    37. public void setBaggage(Baggage baggage) {
    38. this.baggage = baggage;
    39. }
    40. public ValueAdd getValueAdd() {
    41. return valueAdd;
    42. }
    43. public void setValueAdd(ValueAdd valueAdd) {
    44. this.valueAdd = valueAdd;
    45. }
    46. }

  • 相关阅读:
    【ES实战】ES创建Transports客户端时间过长分析
    [教你做小游戏] 《五子棋》怎么判断输赢?你能5分钟交出代码吗?
    90%的软件测试从业者,努力的方向都错了...你呢?
    JavaEE | 一文吃透Cookie
    Ubuntu不显示共享文件夹解决方案
    IIR滤波器
    Spring Cloud Alibaba【授权规则、系统自适应限流、SentinelResource注解配置详解之只配 置fallback】(八)
    【英语:王者进阶_高级别学术阅读】K1.快速摸清段落主题
    Linux与Shell学习--shell系列4--常用的数据类型(数字、字符串和数组)
    Spring学习笔记(2)
  • 原文地址:https://blog.csdn.net/u011294519/article/details/126475055