20145208 实验二 Java面向对象程序设计

实验内容

  1. 初步掌握单元测试和TDD
  2. 理解并掌握面向对象三要素:封装、继承、多态
  3. 初步掌握UML建模
  4. 熟悉S.O.L.I.D原则
  5. 了解设计模式

实验步骤

(一)单元测试

三种代码

  • 伪代码
  • 产品代码
  • 测试代码
  • 在这里我通过一个复数计算的例子来验证这三种代码。
代码需求
  • 实现复数的加法、减法和乘法计算,并输出结果的功能。
伪代码
  • 根据上面的需求,可以先写出程序的伪代码,伪代码是一个程序最好的注释,有助于我们理解问题和解决问题,改程序伪代码如下:
设定两个复数并计算:
两个复数相加
两个复数相减
两个复数相乘
正确格式输出
产品代码
  • 根据伪代码不难编出产品代码,通过老师给的关键方法提示,我定义了设定复数的方法,代码段如下:
public ComplexOf20145208(double m_dRealPart,double m_dImaginPart){
this.m_dImaginPart=m_dImaginPart;
this.m_dRealPart=m_dRealPart;
}
  • 然后根据伪代码的流程来定义计算的三种方法,比如加法,代码如下:
public ComplexOf20145208 Add(ComplexOf20145208 c){
double realPartSum=m_dRealPart+c.m_dRealPart;
double imaginPartSum=m_dImaginPart+c.m_dImaginPart;
return new ComplexOf20145208(realPartSum,imaginPartSum);
}
  • 其他的几种方法都与之类似,不作描述。
  • 在输出的部分需要特别注意一下输出的格式,因为复数部分的符号和有无都有不同情况,所以这我需要在方法中设定几种情况,即复数的系数为整数、0或负数的时候,当然,为了符合全面性,还要包括不属于以上的输出情况,代码如下:
public String toString(){
if (m_dImaginPart>0){
return this.m_dRealPart+"+"+this.m_dImaginPart+"i";
}
else if (m_dImaginPart<0){
return this.m_dRealPart+this.m_dImaginPart+"i";
}
else if (m_dImaginPart==0){
return this.m_dRealPart+"";
}
return "Wrong!";
}
}
  • 到此为止,代码基本上实现了伪代码所描述的功能,可以整理在一起构成一个完整的产品代码,代码如下:
public class ComplexOf20145208 {
private double m_dRealPart;
private double m_dImaginPart;
public ComplexOf20145208(double m_dRealPart,double m_dImaginPart){
this.m_dImaginPart=m_dImaginPart;
this.m_dRealPart=m_dRealPart;
}
public ComplexOf20145208 Add(ComplexOf20145208 c){
double realPartSum=m_dRealPart+c.m_dRealPart;
double imaginPartSum=m_dImaginPart+c.m_dImaginPart;
return new ComplexOf20145208(realPartSum,imaginPartSum);
}
public ComplexOf20145208 Minus(ComplexOf20145208 c){
double realPartMin=m_dRealPart-c.m_dRealPart;
double imaginPartMin=m_dImaginPart-c.m_dImaginPart;
return new ComplexOf20145208(realPartMin,imaginPartMin);
}
public ComplexOf20145208 Multi(ComplexOf20145208 c){
double realPartMul=m_dRealPart*c.m_dRealPart;
double imaginPartMul=m_dImaginPart*c.m_dImaginPart;
return new ComplexOf20145208(realPartMul,imaginPartMul);
}
public String toString(){
if (m_dImaginPart>0){
return this.m_dRealPart+"+"+this.m_dImaginPart+"i";
}
else if (m_dImaginPart<0){
return this.m_dRealPart+this.m_dImaginPart+"i";
}
else if (m_dImaginPart==0){
return this.m_dRealPart+"";
}
return "Wrong!";
}
}
测试代码
  • 在IDEA中建立测试代码很方便,只需要在要进行测试的代码中右键然后在选项中选择GO TO……Test就可以建立一个测试类:

  • 还可以在这里直接选择要测试的内容,IDEA会帮助自动建立相关模块,然后我们就在模块里面输入我们的测试内容了。

  • 对于测试代码,要尽量的全面,首先可以测试常规情况,比如对于复数的计算,就可以先进行如下测试:
@Test
public void testComplex()throws Exception{
assertEquals("7.0+9.0i",new ComplexOf20145208(2,6).Add(new ComplexOf20145208(5,3)).toString());
assertEquals("-3.0+3.0i",new ComplexOf20145208(2,6).Minus(new ComplexOf20145208(5,3)).toString());
assertEquals("10.0+18.0i",new ComplexOf20145208(2,6).Multi(new ComplexOf20145208(5,3)).toString());
}
  • 这个测试就是输出结果符合我的期待值,初步测试了我的代码:

  • 但在仅仅一个测试还是不够的,我需要再输入一些错的测试值,进一步来验证程序的输出:
assertEquals("-7.0+9.0i",new ComplexOf20145208(2,6).Add(new ComplexOf20145208(5,3)).toString());
  • 结果没有让我失望,测试出来我给的输出和输入不匹配的,并且IDEA给出了实际运行出来的结果:

  • 两个测试就够了么?还是远远不够的,在找错误的时候可以多找找边缘值,这里是比较容易出现错误的地方,在复数的计算中,边缘值就是复数i的系数,我们可以测试一下如果系数等于0怎么办吧?代码如下:
assertEquals("0.0",new ComplexOf20145208(0,6).Multi(new ComplexOf20145208(5,0)).toString());
  • 结果是测试通过的:

  • 但是这样还是不够,测试一种错误的输出试试吧:
assertEquals("0.0+0.0i",new ComplexOf20145208(0,6).Multi(new ComplexOf20145208(5,0)).toString());
  • 提是测试错误了,还给出了程序输出的内容:

  • 但是一个程序的测试的范围很大,我刚刚测试的也只是很少的一部分,接下来我再进行一个测试:
assertEquals("18.0i",new ComplexOf20145208(0,6).Multi(new ComplexOf20145208(5,3)).toString());
  • 既然复数的系数为0可以在输出的时候不显示i,那么让实数为0的时候应该只显示18i吧,但是在这里程序让我失望了,测试失败了,我也终于检测到了我的一个缺漏之处,就是没有设定实数为0但虚部不为零的情况:

  • 发现了问题所在就将问题补足,在代码中添加条件限制,代码段如下:
public String toString(){
if (m_dImaginPart > 0) {
if (m_dRealPart==0)
return this.m_dImaginPart+"i";
else
return this.m_dRealPart + "+" + this.m_dImaginPart + "i";
} else if (m_dImaginPart < 0) {
if (m_dRealPart==0)
return this.m_dImaginPart+"i";
else
return this.m_dRealPart + this.m_dImaginPart + "i";
} else if (m_dImaginPart == 0) {
return this.m_dRealPart + "";
}
return "Wrong!";
}
  • 这样我就限定了在实部为0的时候只输出虚部,测试通过:

  • 到这里,我对我的代码的测试就基本完成了,当然,对于测试来说,还有很多测试的余地,但是在本次实验中就不做过多测试了。

(二)面向对象三要素

(1)抽象
  • 抽象一词的本意是指人在认识思维活动中对事物表象因素的舍弃和对本质因素的抽取。抽象是人类认识复杂事物和现象时经常使用的思维工具,抽象思维能力在程序设计中非常重要,"去粗取精、化繁为简、由表及里、异中求同"的抽象能力很大程度上决定了程序员的程序设计能力。
  • 抽象就是抽出事物的本质特征而暂时不考虑他们的细节。对于复杂系统问题人们借助分层次抽象的方法进行问题求解;在抽象的最高层,可以使用问题环境的语言,以概括的方式叙述问题的解。在抽象的较低层,则采用过程化的方式进行描述。在描述问题解时,使用面向问题和面向实现的术语。
  • 程序设计中,抽象包括两个方面,一是过程抽象,二是数据抽象。
(2)封装、继承与多态
  • 面向对象(Object-Oriented)的三要素包括:封装、继承、多态。面向对象的思想涉及到软件开发的各个方面,如面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程实现(OOP)。OOA根据抽象关键的问题域来分解系统,关注是什么(what)。OOD是一种提供符号设计系统的面向对象的实现过程,用非常接近问题域术语的方法把系统构造成“现实世界”的对象,关注怎么做(how),通过模型来实现功能规范。OOP则在设计的基础上用编程语言(如Java)编码。贯穿OOA、OOD和OOP的主线正是抽象。
  • 封装示例
public class Dog {
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String bark(){
return "汪汪";
}
public String toString(){
return "The Dog's color is " + this.getColor() +", and it shouts "+ this.bark() + "!";
}
}
  • 检测示例
public class DogTest {
public static void main(String[] args) {
Dog d = new Dog();
d.setColor("Yellow");
getInfo(d);
}
public static void getInfo(Dog d) {
System.out.println(d.toString());
}
}
  • 输出结果:

利用StarUML软件进行UML建模
  • 选择建立Default Approach工程

  • 选择Design Model

  • 新建class

  • 添加Attribute

  • 进行封装

  • 添加Operation

  • 添加测试类并建立关系

  • 在Tools->Java->Generate code...中生成代码,可能出现如下问题:

  • 只需要在Model->Profiles... 将左边的Java Profile移到右边就可以了

  • 然后就可以选择建模并保存到指定文件夹了:

(三)设计模式初步

(1)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,依赖倒置原则)
  • 因为S.O.L.I.D原则在之前的学习中已经阐述了就不在赘述了。
(2)模式与设计模式
  • 模式是某外在环境(Context) 下﹐对特定问题(Problem)的惯用解决之道(Solution)。模式必须使得问题明晰,阐明为什么用它来求解问题,以及在什么情况下有用,什么情况下不能起作用,每个模式因其重复性从而可被复用,本身有自己的名字,有可传授性,能移植到不同情景下。模式可以看作对一个问题可复用的专家级解决方法。计算机科学中有很多模式:
  • GRASP模式
  • 分析模式
  • 软件体系结构模式
  • 设计模式:创建型,结构型,行为型
  • 管理模式: The Manager Pool 实现模式
  • 界面设计交互模式
  • 这里面最重要的是设计模式,在面向对象中设计模式的地位可以和面向过程编程中的数据结构的地位相当。
(3)设计模式实示例
  • 设计模式可以帮我们以最好的方式来设计系统。设计模式背后是抽象和SOLID原则。

  • 设计模式有四个基本要素:

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

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

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

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

步骤 耗时 百分比
需求分析 5min 5%
设计 15min 15%
代码实现 65min 65%
测试 10min 10%
分析总结 5min 5%

总结

  • 在本次实验中,我学会了测试代码,虽然对于代码进行测试看上去很麻烦,感觉多此一举,但是就像老师所说的,代码中的bug越早越容易发现,如果拖到代码庞大之后再去编写测试的话,工作量太大了,而且一旦出现什么错误,找到BUG是一件十分困难的事情。
  • 那么,通过单元测试,我们就可以很大程度的避免那些错误,也许现在的效果不明显,但是如果我们养成这个习惯,在以后编写大量的代码程序的时候就可以帮助我们队代码查缺补漏,大大的节约我们的时间和成本。

20145208 实验二 Java面向对象程序设计的更多相关文章

  1. 20145208 实验三 Java面向对象程序设计

    20145208 实验三 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步 ...

  2. 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

  3. 20145213《Java程序设计》实验二Java面向对象程序设计实验报告

    20145213<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装,继承,多态 初步掌握UML建模 熟悉S.O. ...

  4. 20145206《Java程序设计》实验二Java面向对象程序设计实验报告

    20145206<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O. ...

  5. 20145308刘昊阳 《Java程序设计》实验二 Java面向对象程序设计 实验报告

    20145308刘昊阳 <Java程序设计>实验二 Java面向对象程序设计 实验报告 实验名称 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面相对象三要素:封 ...

  6. 20145113 实验二 Java面向对象程序设计

    20145113 实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 1.初 ...

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

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1353  姓名:韩玉琪  学号:20135317 成绩:             指导教师:娄嘉 ...

  8. 20145225唐振远 实验二 "Java面向对象程序设计"

    20145225<Java程序设计> 实验二 Java面向对象程序设计 实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S ...

  9. 20162311 实验二 Java面向对象程序设计 实验报告

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

随机推荐

  1. [Derby]数据库操作说明

    1. 创建新数据库 connect 'jdbc:derby:mydb;create=true'; ij> connect 'jdbc:derby:mydb;create=true'; ij> ...

  2. celery 快速入门教程 celery 定时器

    当然首先得安装celery和rabbitmq-server,如果有redis需要安装redis 安装Redis $ yum install redis 启动 Redis $redis-server 检 ...

  3. [转] Paxos算法2-算法过程(实现)

    请先参考前文:Paxos算法1 1.编号处理 根据P2c ,proposer在提案前会先咨询acceptor查看其批准的最大的编号和value,再决定提交哪个value.之前我们一直强调更高编号的pr ...

  4. docker-3 基础命令

    创建镜像 创建镜像的方法有三种: 基于已有的容器创建 基于本地模板导入 基于dockerfile 基于已有的容器创建 主要使用docker commit 命令,命令格式: docker commit ...

  5. Geoserver发布Oracle数据

    在Geoserver安装包中,默认是不能发布Oracle数据库里的数据的,只能发布postgis.shp等数据,详细如截图: 如果想发布oracle数据,得安装相应版本的关于oracle数据源的插件, ...

  6. UVALive 6449 IQ Test --高斯消元?

    题意:给你一串数字,问这串数字符合f[n] = a*f[n-1],f[n] = a*f[n-1]+b*f[n-2],f[n] = a*f[n-1]+b*f[n-2]+c*f[n-3]这几个方程中的哪个 ...

  7. NYOJ----1124数量

    数量 时间限制:200 ms  |  内存限制:65535 KB 难度:0 描述 HJS大牛想去街上吃饭,街道旁边拴着很多狗,他想我堂堂......(省略n个字)岂会被狗咬,所以他很牛的从狗的面前经过 ...

  8. RabbitMQ 一二事 - 简单队列使用

    消息队列目前流行的有三种 1. RabbitMQ 2. ActiveMQ 3. Kafka 这三种都非常强大,RabbitMQ目前用的比较多,也比较流行,阿里也在用 ActiveMQ是阿帕奇出品,但是 ...

  9. 数据结构Java实现05----栈:顺序栈和链式堆栈

    一.堆栈的基本概念: 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

  10. IT技术博客收藏

    1. coolshell.cn 特点: 每篇都是精品 2. 云风 特点: 3. 阮一峰的博客 特点:高精深 3. offbye涛声依旧-全端技术博客 特点: android的开发技术比较多,非常值得一 ...