第二次Blog作业

第二次Blog作业
—————————————————————————————————————————
前言
—————————————————————————————————————————
一. 题目集中蕴含的知识点:

  1. 面向对象编程
    • 类与对象:定义了Airplane、Person、MainCustomer、PostCustomer、GetCustomer、Order、Thing等类,并创建实例。
    • 继承:PostCustomer和GetCustomer继承自Person类,复用了姓名、电话、地址等属性。
    • 抽象类:Person类被定义为抽象类,提供通用属性但不实例化。
    • 封装:使用private修饰符隐藏类的内部实现,通过公共方法(如getName())访问属性。
  2. 接口与实现
    • 接口:定义FreightCalculator接口,包含计算运费的抽象方法。
    • 实现:DefaultFreightCalculator类实现该接口,提供具体的运费计算逻辑。
  3. 集合框架
    • ArrayList:使用List和List存储多个货物和支付信息,支持动态扩展。
  4. 方法设计与重载
    • 方法参数与返回值:如calculateFreight(Thing thing, int form)接收货物和类型参数,返回运费。
    • 私有方法:calculateByWeight作为辅助方法,被calculateFreight调用。
  5. 输入输出处理
    • Scanner 类:从控制台读取用户输入(如客户信息、货物参数、航班信息等)。
    • 格式化输出:使用System.out.println打印订单和货物明细报告。
  6. 条件与循环
    • switch 语句:根据货物类型(普通、危险品、加急品)选择不同的运费计算规则。
    • for 循环:遍历货物列表计算总重量和生成报告。
  7. 异常处理
    • 隐式异常:未显式使用try-catch,但 Scanner 读取输入时可能抛出异常(如输入非数字)。

二. 关于题目集的题量及难度:
1. 对于题目的数量,两次题目集均为3道题目,且大部分题目是对之前题目的迭代。
2. 总体上难度不算太大,均是考查对“java语言程序设计”中继承与多态,接口等主要知识点的运用以及对题目要求的分析。
—————————————————————————————————————————
设计与分析
—————————————————————————————————————————
一. 第一次作业:

  1. 作业要求:
    本次题目模拟某客户到该航空公司办理一次货运业务的过程: 航空公司提供如下信息: 航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班 日期,航班最大载重量) 客户填写货运订单并进行支付,需要提供如下信息:  客户信息(姓名,电话号码等)  货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)  运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选 航班号,订单日期)  支付方式(支付宝支付、微信支付) 注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独计费。
    程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信 息报表及货物明细报表。
    本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开 闭原则以及合成复用原则、依赖倒转原则

  2. 实现方式:
    通过继承与多态实现类与类之间的调用实现以达到题目要求。

  3. 类图:

  4. 复杂度分析:

    a) DefaultFreightCalculator.Math.max()

class DefaultFreightCalculator implements FreightCalculator {
    @Override
    public double calculateFreight(Thing thing) {
        double chargeableWeight = thing.calculateChargeableWeight();
        if (chargeableWeight < 20&&chargeableWeight>=0) {
            return chargeableWeight * 35;
        } else if (chargeableWeight < 50) {
            return chargeableWeight * 30;
        } else if (chargeableWeight < 100) {
            return chargeableWeight * 25;
        } else {
            return chargeableWeight * 15;
        }
    }
}
  • 复杂度为 6.9.3 。在计算运费时,使用Math.max() 计算逻辑可能涉及多个业务规则和数
    据处理步骤,导致方法复杂度较高。

  • 优化建议:
    提取辅助方法:将复杂的条件判断逻辑拆分为独立的小方法

    b) PostCustomer.PostCustomer()


class PostCustomer extends Person {
    public PostCustomer(String name, String phoneNumber, String address) {
        super(name, phoneNumber, address);
    }
}

  • 复杂度为 6.27 ,紧随其后。构造函数有这样的复杂度,可能是因为在创建PostCustomer对象时,需要初始化大量属性,并且可能涉及与其他类或模块的交互,比如验证客户信息、与数据库连接获取默认值等一系列操作,使得代码逻辑变得复杂。
  • 优化建议:
    分步初始化:将部分初始化逻辑延迟到专门的 init 方法
    依赖注入:通过参数提供已初始化的依赖对象
  1. Bug分析:
  • 在计算货物总重量时,会出现答案错误的情况,这里在逐步加重量时应该加的是货物的费重(实际质量和体积重量的最大值)。
  • 循环输入物品信息时会有部分信息加入不到List中,
    同过调整add()的位置得以解决。

二.第二次作业:

  1. 作业要求:
    本次题目模拟某客户到该航空公司办理一次货运业务的过程: 航空公司提供如下信息: 航班信息(航班号,航班起飞机场,航班降落机场,航班日期,航班最大载 重量) 2 客户填写货运订单并进行支付,需要提供如下信息:  客户信息(姓名,电话号码等)  货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)  运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选 航班号,订单日期)  支付方式(支付宝支付、微信支付、现金支付) 注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独计费。
    程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信 息报表及货物明细报表
    本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开 闭原则以及合成复用原则、依赖倒转原则

  2. 实现方法:
    通过继承与多态实现类与类之间的调用实现和条件选择以达到题目要求。

  3. 类图:

  4. 复杂度分析:

    DefaultFreightCalculator.Math.max()

class DefaultFreightCalculator implements FreightCalculator {
    @Override
    public double calculateFreight(Thing thing, int form) {
        double chargeableWeight = thing.calculateChargeableWeight();
        switch (form) {
            case 1: // 普通货物
                return calculateByWeight(chargeableWeight, new double[]{35, 30, 25, 15});
            case 2: // 危险品
                return calculateByWeight(chargeableWeight, new double[]{80, 50, 30, 20});
            case 3: // 加急品
                return calculateByWeight(chargeableWeight, new double[]{60, 50, 40, 30});
            default:
                return 0;
        }
    }

    private double calculateByWeight(double weight, double[] rates) {
        if (weight < 0) {
            return 0;
        } else if (weight < 20) {
            return weight * rates[0];
        } else if (weight < 50) {
            return weight * rates[1];
        } else if (weight < 100) {
            return weight * rates[2];
        } else {
            return weight * rates[3];
        }
    }
}
  • 复杂度为 6.10.3.0 (这里数据格式可能有误,推测是 6 左右 ) ,是所有方法中复杂度最高的。在运费计算场景下,可能需要综合货物重量、体积、运输距离、运输方式、优惠策略等多种因素来确定最大计费标准或合适的费用计算值。比如,可能要在不同的计费规则(如按重量、按体积、按距离分段计费 )中进行比较和判断,还可能涉及各种优惠条件(如会员折扣、满减等 )的逻辑处理,导致方法内条件判断、循环等逻辑嵌套较多,复杂度升高。

  • 措施:把不同计费规则(如重量计费、距离计费、特殊条件计费等)拆分为独立方法。例如,将按重量计算运费的逻辑提取到calculateWeightBasedFreight() 方法,按距离计算的逻辑提取到calculateDistanceBasedFreight() 方法,使主方法逻辑更清晰。

    Airplane.Airplane()

public Airplane(String number, String startCity, String endCity, String date, double maxWeight) {
        this.number = number;
        this.startCity = startCity;
        this.endCity = endCity;
        this.date = date;
        this.maxWeight = maxWeight;
    }
  • 复杂度为 1.5.2.0 ,构造函数有一定复杂度,可能是在创建Airplane对象时,需要初始化众多属性,如飞机型号、座位数、航程、载重等。并且可能还需要进行一些属性的验证或关联操作,比如根据飞机型号获取默认的座位布局、航程参数等,涉及多个数据来源和处理逻辑,使得复杂度上升。

  • 措施:将属性初始化和关联操作分散到多个私有方法中。比如,把座位数和座位布局相关初始化放到initializeSeating() 方法,航程和载重相关初始化放到initializeFlightParameters() 方法,然后在构造函数中调用这些方法,降低构造函数复杂度

    5.Bug分析:

  • 在计算货物总重量时,会出现答案错误的情况,这里在逐步加重量时应该加的是货物的费重(实际质量和体积重量的最大值)。

—————————————————————————————————————————
改进建议
—————————————————————————————————————————
 1. 在第一次作业缺乏对异常处理的进一步分析,需要对异常分析添加代码以提高代码的可维护性。
 2. 第二次作业中对货物情况的分析,客户的类型均是以else-if进行处理的,这极大的增加了代码的复杂度,需要将这部分的功能分成多个子类实现,以增加代码的可扩展性
 两次代码的main()方法均太过于复杂,应该分离出工具类减轻mian()的运行负担。
—————————————————————————————————————————
总结
—————————————————————————————————————————
通过本阶段两次题目集的实践,我系统掌握了 Java 面向对象编程的核心概念与设计原则,并在实际项目中体会到代码结构优化的重要性。尽管在异常处理代码扩展性等方面仍有不足,但通过明确学习目标结合课程改进建议,未来将更注重代码的健壮性与可维护性,逐步提升软件开发的综合能力。感谢教师的指导与课程设计,期待后续学习中能进一步深化知识应用,积累更多实战经验。

一、知识与技能的全面提升
(一)编程基础与核心能力强化
通过本阶段学习,深入掌握了Java面向对象编程的核心概念,包括类的封装、继承与多态的实际应用。例如,在设计货运系统时,将客户信息抽象为Person类,通过PostCustomerGetCustomer子类继承其属性,实现代码复用;利用接口FreightCalculator定义运费计算规则,通过不同实现类(如DefaultFreightCalculator)实现策略模式,体现了依赖倒转原则,增强了系统的可扩展性。
在数据处理方面,熟练运用ArrayList等集合框架管理批量数据(如货物列表、支付信息),掌握了循环遍历、数据统计(如总重量计算)和条件判断(如根据客户类型应用折扣)的技巧。同时,通过Scanner完成控制台输入处理,并使用格式化输出(System.out.println)生成订单报表,提升了输入输出与业务逻辑的整合能力。

(二)问题解决与系统设计思维
通过两次迭代作业,学会了将复杂需求拆解为模块化设计。例如,将货运系统拆分为航班、客户、订单、货物、支付等独立模块,每个模块对应特定的类,遵循单一职责原则,降低了代码复杂度。在处理体积重量计算、阶梯费率应用等业务逻辑时,通过数学公式推导和逻辑验证(如取实际重量与体积重量的最大值作为计费依据),提升了问题分析与算法设计能力。
二、作业过程的深入剖析
(一)第一次作业:基础搭建与逻辑疏漏
首次作业聚焦于基础功能实现,完成了航班、客户、订单等类的定义,并通过Scanner实现了控制台输入。但在设计运费计算逻辑时,未充分考虑货物类型的多样性(如普通、危险品、加急品),仅使用单一费率规则,导致代码扩展性不足。此外,Main方法承担了过多职责(输入读取、业务逻辑、报表生成),违反了单一职责原则,代码结构较为臃肿。
(二)第二次作业:迭代优化与设计缺陷
第二次作业扩展了货物类型和支付方式,通过switch语句实现不同货物的费率区分,并引入折扣机制(个人客户9折、企业客户8折)。然而,货物类型的判断仍依赖大量else-if语句,未通过多态或枚举类型优化,代码复杂度较高。同时,输入处理逻辑未封装为工具类,导致Main方法代码冗余,且缺乏对无效输入的校验(如非数字类型输入),程序健壮性不足。
三、对课程的建议与展望
作业与实验设计改进

  1. 渐进式设计要求:在作业中明确分阶段引入设计原则,例如第一次作业重点练习封装与继承,第二次作业强制使用接口与多态,第三次作业要求应用工厂模式或策略模式,引导学生逐步提升设计能力。
  2. 增加非功能需求:在作业说明中加入代码规范(如命名规则、注释要求)、性能优化(如算法复杂度控制)和异常处理的评分项,促使学生关注代码的可维护性与健壮性。
  3. 提供分层参考方案:作业后发布基础版与优化版参考代码,对比不同设计的优缺点(如使用枚举vselse-if判断货物类型),帮助学生理解设计模式的实际效益。

(四)个人学习展望
未来将重点提升以下能力:
1. 设计模式应用:学习使用装饰器模式扩展货物附加服务(如保价、代收货款),使用观察者模式实现订单状态实时通知。
2.通过本阶段学习,深刻认识到面向对象编程的灵活性与设计原则的重要性。期待后续课程能更深入结合实际场景,引导学生从“实现功能”向“设计可扩展系统”进阶,进一步提升软件开发的系统性思维与工程能力。

posted @ 2025-05-18 20:02  大头酱军  阅读(31)  评论(0)    收藏  举报