20155314 2016-2017-2 《Java程序设计》实验二 Java面向对象程序设计
20155314 2016-2017-2 《Java程序设计》实验二 Java面向对象程序设计
实验内容
-
初步掌握单元测试和TDD
-
理解并掌握面向对象三要素:封装、继承、多态
-
初步掌握UML建模
-
熟悉S.O.L.I.D原则
-
了解设计模式
实验知识点总结
(一)单元测试
(1) 三种代码
- 伪代码
- 产品代码
- 测试代码
(2) TDD(Test Driven Devlopment, 测试驱动开发)
-
先写
测试代码
,然后再写产品代码
的开发方法叫“测试驱动开发”(TDD)。 -
TDD的一般步骤:
- 明确当前要完成的功能,记录成一个测试列表
- 快速完成编写针对此功能的测试用例
- 测试代码编译不通过(没产品代码呢)
- 编写产品代码
- 测试通过
- 对代码进行重构,并保证测试通过(重构下次实验练习)
- 循环完成所有功能的开发
-
基于TDD,我们不会出现过度设计的情况,需求通过测试用例表达出来了,我们的
产品代码
只要让测试通过就可以了。 -
TDD的编码节奏:
- 增加测试代码,JUnit出现红条
- 修改产品代码
- JUnit出现绿条,任务完成
(二)面向对象三要素
(1)抽象
- 抽象一词的本意是指人在认识思维活动中对事物表象因素的舍弃和对本质因素的抽取。抽象是人类认识复杂事物和现象时经常使用的思维工具,抽象思维能力在程序设计中非常重要,"去粗取精、化繁为简、由表及里、异中求同"的抽象能力很大程度上决定了程序员的程序设计能力。
- 抽象就是抽出事物的本质特征而暂时不考虑他们的细节。对于复杂系统问题人们借助分层次抽象的方法进行问题求解;在抽象的最高层,可以使用问题环境的语言,以概括的方式叙述问题的解。在抽象的较低层,则采用过程化的方式进行描述。在描述问题解时,使用面向问题和面向实现的术语。
- 程序设计中,抽象包括两个方面:
- 过程抽象
- 数据抽象
(2)封装、继承与多态
-
面向对象(Object-Oriented)的三要素包括:封装、继承、多态。
-
面向对象的思想涉及到软件开发的各个方面,贯穿OOA、OOD和OOP的主线正是抽象:
- 面向对象分析(OOA):根据抽象关键的问题域来分解系统,关注是什么(what)
- 面向对象设计(OOD):是一种提供符号设计系统的面向对象的实现过程,用非常接近问题域术语的方法把系统构造成“现实世界”的对象,关注怎么做(how),通过模型来实现功能规范
- 面向对象编程实现(OOP):在设计的基础上用编程语言(如Java)编码
-
OOD中建模会用图形化的建模语言UML(Unified Modeling Language),UML是一种通用的建模语言,我们实验中使用umbrello进行建模,Windows中推荐大家使用 StarUML。
-
过程抽象的结果是函数,数据抽象的结果是抽象数据类型(Abstract Data Type,ADT),类可以作具有继承和多态机制的ADT。数据抽象才是OOP的核心和起源。
-
OO三要素的第一个要素是封装,封装就是将数据与相关行为包装在一起以实现信息就隐藏。
-
封装实际上使用方法(method)将类的数据隐藏起来,控制用户对类的修改和访问数据的程度,从而带来模块化(Modularity)和信息隐藏(Information hiding)的好处;接口(interface)是封装的准确描述手段。
-
UML建模:
- 在UML 里,一个类的属性能显示它的名字,类型,初始化值,属性也可以显示private,public,protected。 类的方法能显示它们的方法名,参数,返回类型,以及方法的private,public,protected属性。其中:
- +表示public
-
表示protected
- -表示private
- UML类图要展示类之间的静态关系,UML中依赖用带箭头的直线表示
- UML类图中继承的表示法是用一个带三角的直线指向父类
- 在UML 里,一个类的属性能显示它的名字,类型,初始化值,属性也可以显示private,public,protected。 类的方法能显示它们的方法名,参数,返回类型,以及方法的private,public,protected属性。其中:
-
继承指一个类的定义可以基于另外一个已经存在的类,即子类基于父类,从而实现父类代码的重用。既存类称作基类、超类、父类(base class、super class、parent class),新类称作派生类、继承类、子类(derived class、inherited class、child class)。继承关系表达了”Is a kind of“的关系,称为“ISA”关系。继承的关键在于确认子类为父类的一个特殊类型。
-
继承是实现软件可重用的根基,是提高软件系统的可扩展性与可维护性的主要途径。
-
以封装为基础,继承可以实现代码复用,需要注意的是,继承更重要的作用是实现多态。
-
面向对象中允许不同类的对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式,我们称此现象为多态性。Java中,多态是指不同的类对象调用同一个签名的成员方法时将执行不同代码的现象。多态是面向对象程序设计的灵活性和可扩展性的基础。
★在Java中,当我们用父类声明引用,用子类生成对象时,多态就出现了
(三)设计模式初步
(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,依赖倒置原则)
(2)模式与设计模式
模式是某外在环境(Context) 下﹐对特定问题(Problem)的惯用解决之道(Solution)。模式必须使得问题明晰,阐明为什么用它来求解问题,以及在什么情况下有用,什么情况下不能起作用,每个模式因其重复性从而可被复用,本身有自己的名字,有可传授性,能移植到不同情景下。模式可以看作对一个问题可复用的专家级解决方法。
计算机科学中有很多模式:
- GRASP模式
- 分析模式
- 软件体系结构模式
- 设计模式:创建型,结构型,行为型
- 管理模式: The Manager Pool 实现模式
- 界面设计交互模式
- …
这里面最重要的是设计模式,在面向对象中设计模式的地位可以和面向过程编程中的数据结构的地位相当。
(3)设计模式实示例
- 设计模式(design pattern)提供一个用于细化软件系统的子系统或组件,或它们之间的关系图,它描述通信组件的公共再现结构,通信组件可以解决特定语境中的一个设计问题
- 设计模式有四个基本要素:
- Pattern name:描述模式,便于交流,存档
- Problem:描述何处应用该模式
- Solution:描述一个设计的组成元素,不针对特例
- Consequence:应用该模式的结果和权衡(trade-offs)
- 除SOLID原则外还有很多其它的面向对象原则,如:
- "组合替代继承":这是说相对于继承,要更倾向于使用组合
- "笛米特法则":这是说"你的类对其它类知道的越少越好"
- "共同封闭原则":这是说"相关类应该打包在一起"
- "稳定抽象原则":这是说"类越稳定,越应该由抽象类组成"
(四)练习
1.使用TDD的方式设计关实现复数类Complex。
public class Complex {
// 定义属性并生成getter,setter
double RealPart; //复数的实部
double ImagePart; //复数的虚部
void setReal(double r){
this.RealPart=r;
}
void setImage(double i){
this.ImagePart=i;
}
double getReal(){
return this.RealPart;
}
double getImage(){
return this.ImagePart;
}
// 定义构造函数
public Complex(){
}
public Complex(double R,double l){
this.RealPart=R;
this.ImagePart=l;
}
//Override Object
public boolean equals(Complex a){
return (this.RealPart==a.RealPart&&this.ImagePart==a.ImagePart);
}
public String toString(){
if(this.ImagePart<0) return this.RealPart+""+this.ImagePart+"i";
else return this.RealPart+"+"+this.ImagePart+"i";
}
// 定义公有方法:加减乘除
Complex ComplexAdd(Complex a){ // 加
return new Complex(this.RealPart+a.RealPart,this.ImagePart+a.ImagePart);
}
Complex ComplexSub(Complex a){ // 减
return new Complex(this.RealPart-a.RealPart,this.ImagePart-a.ImagePart);
}
Complex ComplexMulti(Complex a){ // 乘
double r=this.RealPart*a.RealPart-this.ImagePart*a.ImagePart;
double i=this.RealPart*a.ImagePart+this.ImagePart*a.RealPart;
return new Complex(r,i);
}
Complex ComplexDiv(Complex a){ // 除
Complex a1=new Complex();
if(a.equals(a1)){ // 防止非法输入导致零除错误
System.out.println("输入的被除数不能同时为0!\n");
return null;
}
/*if(this.RealPart==0&&a.ImagePart==0){ // 防止非法输入导致零除错误
System.out.println("输入的被除数不能同时为0!\n");
return null;
}*/
double x=this.RealPart*this.RealPart+a.ImagePart*a.ImagePart;
double r=(this.RealPart*a.RealPart+this.ImagePart*a.ImagePart)/x; // 实部:(a*c+b*d)/(a*a+d*d)
double i=(this.ImagePart*a.RealPart-this.RealPart*a.ImagePart)/x; // 虚部:(b*c-a*d)/(a*a+d*d)
return new Complex(r,i);
}
}
用IDEA生成的类图如下:
2.实验报告中统计自己的PSP(Personal Software Process)时间
步骤 | 耗时 | 百分比 |
---|---|---|
需求分析 | 6min | 6.5% |
设计 | 20min | 21.7% |
代码实现 | 25min | 27.2% |
测试 | 11min | 12.0% |
分析总结 | 30min | 32.6% |
实验过程中遇到的问题及解决
关于使用StarUML建模软件中遇到的问题
实验体会与总结
“自己动手,丰衣足食。”
本次Java实验让我更切身感受到动手实践的重要性,避免眼高手低,勤于动手、热衷实践才是学好一切的王道。
参考资料
- 实验二 Java面向对象程序设计 - 娄老师 - 博客园
- 实验二《Java面向对象程序设计》的一点说明 - 娄老师 - 博客园
- Intellj IDEA 简易教程
- Intellij idea生成类图和导出类图
- StarUML逆向工程: 通过代码生成类图
- 从 Java 代码逆向工程生成 UML 类图和序列图
- Intellij IDEA中安装&使用PlantUML画时序图、类图等
- 《UML精粹》
- 《构建之法 (电子版)》,著者邹欣Blog
- 《深入浅出设计模式》
- 《解析极限编程》
- 《单元测试之道》
- 《代码大全》
- 《代码的抽象三原则》