• JAVA课程实验报告 实验二 Java面向对象程序设计


    北京电子科技学院(BESTI)

                 

    课程:Java程序设计  班级:1353  姓名:韩玉琪  学号:20135317

    成绩:             指导教师:娄嘉鹏    实验日期:2015.5.6

    实验密级:         预习程度:         实验时间:15:50--20:50

    仪器组次:         必修/选修: 选修            实验序号:2

    实验名称:实验二 Java面向对象程序设计                                          

    实验目的与要求:

    1. 初步掌握单元测试和TDD                               

    2. 理解并掌握面向对象三要素:封装、继承、多态    

    3. 初步掌握UML建模                                         

    4. 熟悉S.O.L.I.D原则                                       

    5. 了解设计模式                                              

    实验仪器:

    名称

    型号

    数量

    PC

    Lenovo

    1

    实验楼环境

    /

    1

    Eclipse

    /

    1

    一、实验内容及步骤

    (一)单元测试

    1、 三种代码

    需求:我们要在一个MyUtil类中解决一个百分制成绩转成“优、良、中、及格、不及格”五级制成绩的功能。

    (1)伪代码

     

    (2)产品代码

     

    (3)测试代码

     

    因为是自己写的代码,没有照着提示一步步做,所以,没有出现很多问题。

    2、TDD(Test Driven Devlopment, 测试驱动开发)

    (1)概念:先写测试代码,然后再写产品代码的开发方法叫“测试驱动开发”(TDD)。

    (2)TDD的一般步骤如下:

    •  明确当前要完成的功能,记录成一个测试列表

    •  快速完成编写针对此功能的测试用例

    •  测试代码编译不通过(没产品代码呢)

    •  编写产品代码

    •  测试通过

    •  对代码进行重构,并保证测试通过(重构下次实验练习)

    •  循环完成所有功能的开发

    (3)优势:基于TDD,我们不会出现过度设计的情况,需求通过测试用例表达出来了,我们的产品代码只要让测试通过就可以了。

    (4)将百分制转五分制改写成TDD

    代码层次结构:

     

    运行:

     

    假设开始没有将100考虑进去(错误情况):

     

    (5)TDD的编码节奏是:

    •  增加测试代码,JUnit出现红条

    •  修改产品代码

    •  JUnit出现绿条,任务完成

    (二)面向对象三要素

    1、抽象

    (1)“去粗取精、化繁为简、由表及里、异中求同”的能力

    (2)过程抽象、数据抽象

    2、封装、继承与多态

    (1)面向对象的三要素:封装、继承、多态。

    (2)面向对象的思想涉及到软件开发的各个方面,如面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程实现(OOP)。OOA根据抽象关键的问题域来分解系统,关注是什么(what)。贯穿OOA、OOD和OOP的主线正是抽象。

    OOD中建模会用图形化的建模语言UML(Unified Modeling Language),UML是一种通用的建模语言。

    (3)封装

    封装实际上使用方法(method)将类的数据隐藏起来,控制用户对类的修改和访问数据的程度,从而带来模块化(Modularity)和信息隐藏(Information hiding)的好处;接口(interface)是封装的准确描述手段。

    3、例

    (1)Dog类通过使用类和访问控制(private,public)隐藏了属性color,开放了接口setColor(),getColor(),bark()和toString。Dog类是一个模块,我们可以通过下面的代码使用它,测试代码与运行结果如下:

     

     

    (2)我们可以用UML中的类图来描述类Dog:

     

    在UML 里,一个类的属性能显示它的名字,类型,初始化值,属性也可以显示private,public,protected。 类的方法能显示它们的方法名,参数,返回类型,以及方法的private,public,protected属性。其中:•    +表示public •    #表示 protected •    -表示 private

    使用UML可以让我们不必关注细节。

    (3)这时的测试类:

     

    注意:UML类图要展示类之间的静态关系,AnimalTest类依赖Dog类和Cat类,UML中依赖用带箭头的直线表示。

    对应代码:

     

    (3)Dog类和Cat类都有Color属性和相应的set和get方法,明显违反了前面提到的DRY原则,我们可以通过继承解决这个问题,把Color属性和相应方法放到父类Animal中,如以下UML较图所示:

    (注意UML类图中继承的表示法,是用一个带三角的直线指向父类)

     

    以封装为基础,继承可以实现代码复用,需要注意的是,继承更重要的作用是实现多态。多态是面向对象程序设计的灵活性和可扩展性的基础。

    我们再看看上一个类图,我们可以进一步抽象,把Dog类中的bark()和Cat类中的meow()抽象成一个抽象方法shout(),Dog类和Cat类中覆盖这个方法,如以下UML图所示:

     

    代码运行:

     

    (三)设计模式初步

    1、S.O.L.I.D原则

    如何借助抽象思维用好三要素特别是多态是非常困难的,S.O.L.I.D类设计原则是一个很好的指导:

    •  SRP(Single Responsibility Principle,单一职责原则)

    •  OCP(Open-Closed Principle,开放-封闭原则)

    •  LSP(Liskov Substitusion Principle,Liskov替换原则)

    •  ISP(Interface Segregation Principle,接口分离原则)

    •  DIP(Dependency Inversion Principle,依赖倒置原则)

    2、模式与设计模式

    模式是某外在环境(Context) 下﹐对特定问题(Problem)的惯用解决之道(Solution)。模式必须使得问题明晰,阐明为什么用它来求解问题,以及在什么情况下有用,什么情况下不能起作用。每个模式因其重复性从而可被复用,本身有自己的名字,有可传授性,能移植到不同情景下。模式可以看作对一个问题可复用的专家级解决方法。

    计算机科学中有很多模式:

    •  GRASP模式

    •  分析模式

    •  软件体系结构模式

    •  设计模式:创建型,结构型,行为型

    •  管理模式: The Manager Pool 实现模式

    •  界面设计交互模式

    •  …

    3、设计模式实示例

    (1)设计模式(design pattern)提供一个用于细化软件系统的子系统或组件,或它们之间的关系图,它描述通信组件的公共再现结构,通信组件可以解决特定语境中的一个设计问题。

    设计模式背后是抽象和SOLID原则。

    (2)设计模式有四个基本要素:

    •  Pattern name:描述模式,便于交流,存档

    •  Problem:描述何处应用该模式

    •  Solution:描述一个设计的组成元素,不针对特例

    •  Consequence:应用该模式的结果和权衡(trade-offs)

    (3)了解设计模式可能会存在的过度设计问题以及如何避免它。

    (四)练习

    1、使用TDD的方式设计关实现复数类Complex。

    (1)伪代码

     

    (2)产品代码

    //复数打印、相加、相减

    public class Complex {

        private int sh,xu;

        Complex(){

             this.sh=0;

             this.xu=0;

        }

        Complex(int sh){

             this.sh=sh;

             this.xu=0;

        }

        Complex(int sh,int xu){

             this.sh=sh;

             this.xu=xu;

        }

        public void addFu(Complex p1,Complex p2){

             System.out.println("这两个复数的和为:");

             this.sh=p1.sh+p2.sh;

             this.xu=p1.xu+p2.xu;

             print();

        }

        public void minusFu(Complex p1,Complex p2){

             System.out.println("这两个复数的差为:");

             this.sh=p1.sh-p2.sh;

             this.xu=p1.xu-p2.xu;

             print();

        }

        public void outputFu(){

             System.out.println("复数的值为:");

             print();

        }

        public void print(){

             if(this.xu>0){

                   System.out.println(this.sh+"+"+this.xu+"i");

             }else if(this.xu<0){

                   System.out.println(this.sh+""+this.xu+"i");

             }else{

                   System.out.println(this.sh);

             }

        }

    }

    (3)测试代码

    (4)编写代码时遇到的问题

    (开始的时候没有把功能抽取出来,写的很多,然后抽取了print功能就少了很多。)

    最开始设计的伪代码是这样的:

     

    然后设计的代码测试出来是这样的:

     

    虚数部分如果为负数打印出来“+ -”两个符号。所以将两种情况分开。

    但是打印写出来又出现了新情况:

     

    虚部为负数的时候实部没有打印出来,而虚部成了两者的和,再看自己写的代码,发现当虚部小于0时,实部和虚部之间没有加上字符隔开:

     

    它们就直接做了加法,所以加上一个空字符:

     

    测试与计算一致,完成!

    2、实验报告中统计自己的PSP(Personal Software Process)时间

    步骤

    耗时

    百分比

    需求分析

    54min

    18%

    设计

    75min

    25%

    代码实现

    63min

    21%

    测试

    63min

    21%

    分析总结

    45min

    15%

    3.总结单元测试的好处

    (1)使可以放心的修改测试用代码而不用担心会影响设计的测试代码。

    (2)从调用者的角度看自己写的代码,与从编写的角度还是不太一样的,在编写者的角度,就会想着如何方便迅速的完成整个代码,但是从调用者的角度,就会考虑别人使用的时候是否方便,更注重测试和调用。

    (3)测试本身是被测代码的用法说明,替代了一部分代码功能,迫使自己要将被测代码设计得更加独立地去完成某个或某几个功能。

    二、实验感想

    1、这次实验耗费了很长时间,最后都要做不下去了。我深深体会到网络的重要性和学习新方法、使用新工具的能力的重要性。

    2、UML图有点抽象,在虚拟机上实现的时候操作不熟练,刚开始一直没明白怎么把那个框调出来(因为实验楼虚拟机一直出问题,自己没有静下心来看操作步骤上“单击工具栏上的类图标,再在class diagram(类图)中单击一下”),之后是那条箭头画不上去,百度教程,应该是先点击工具栏上的箭头图标(实现关系)然后点击起始的类,出现一条虚线,再点击指向的类。终于把能图画出来了。

    3、TDD的方式例题的测试代码看得懂,但是自己编写的时候就不知道哪些语句怎么用,只好用自己写的测试代码,可能这样不算严格TDD方式,但是我觉得这样的思想对我自己设计某些独立功能是有很大帮助的。

    4、做练习代码的时候,一看到实现复数类不知道具体是要做什么,就上网搜了一下“Complex”,发现有输出、加法、减法的功能,然后我就按着这样的思路编写了伪代码。开始的时候没有把功能抽取出来,啰嗦的写了很多,然后抽取了print功能,将每一项功能单独出来,代码一下就变少了。

    然后我写完上述报告后,看到老师给的复数类还有乘法的功能,我就把代码翻出来,再实现了一下乘法的功能:

     

    运行:

     

    这个时候我觉得自己比任何时候都能理解抽象的好处,每一个功能一旦抽象、封装起来,再增添新功能时调用起来特别方便。

  • 相关阅读:
    HOJ 2139 Spiderman's workout(动态规划)
    FZU 2107 Hua Rong Dao(dfs)
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
  • 原文地址:https://www.cnblogs.com/hyq20135317/p/4483680.html
Copyright © 2020-2023  润新知