课程:Java程序设计 班级:1352 姓名:黄伟业 学号:20135315
成绩: 指导教师:娄嘉鹏 实验日期:2015.5.7
实验密级: 预习程度: 实验时间:15:50--20:50
仪器组次: 必修/选修: 选修 实验序号:2
实验目的:
1.掌握单元测试和TDD
2. 理解并掌握面向对象三要素:封装、继承、多态
3. 初步掌握UML建模
4. 熟悉S.O.L.I.D原则
5. 了解设计模式
实验仪器:
名称 | 型号 | 数量 |
PC | Lenovo | 1 |
实验楼环境 | / | 1 |
Eclipse | / | 1 |
一、实验内容及步骤
一、 单元测试和TDD
代码1:
public class MyUtil{
public static String percentage2fivegrade(int grade){
if ((grade < 0))
return "错误";
else if (grade < 60)
return "不及格";
else if (grade < 70)
return "及格";
else if (grade < 80)
return "中等";
else if (grade < 90)
return "良好";
else if (grade <= 100)
return "优秀";
else
return "错误";
}
}
代码2:
import org.junit.Test;
import junit.framework.TestCase;
public class MyUtilTest extends TestCase {
@Test
public void testNormal() {
assertEquals("不及格", MyUtil.percentage2fivegrade(55));
assertEquals("及格", MyUtil.percentage2fivegrade(65));
assertEquals("中等", MyUtil.percentage2fivegrade(75));
assertEquals("良好", MyUtil.percentage2fivegrade(85));
assertEquals("优秀", MyUtil.percentage2fivegrade(95));
}
}
二、 面向对象三要素
代码1:
public class AnimalTest {
public static void main(String[]args){
Dog d=new Dog();
d.setColor("Yellow");
getInfo(d);
Cat c=new Cat();
c.setColor("Black");
getInfo(c);
}
public static void getInfo(Dog d){
System.out.println(d.toString());
}
public static void getInfo(Cat c){
System.out.println(c.toString());
}
}
代码2:
package dog;
public class DogTest {
public static void main(String[] args){
Dog g=new Dog();
g.setColor("Yellow");
getInfo();
}
public static void getInfo(Dog d){
System.out.println(d.toString());
}
}
代码3:
public abstract class Animal {
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public abstract String shout();
}
public class Dog extends Animal{
public String shout(){
return "汪汪";
}
public String toString(){
return "The Dog's color is " + this.getColor() +", and it shouts "+ this.shout() + "!";
}
}
public class Cat extends Animal{
public String shout(){
return "喵喵";
}
public String toString(){
return "The Cat's color is " + this.getColor() +", and it shouts "+ this.shout() + "!";
}
}
三、设计模式实示例
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,依赖倒置原则)
OCP是OOD中最重要的一个原则,OCP的内容是:
software entities (class, modules, function, etc.) should open for extension,but closed for modification.
软件实体(类,模块,函数等)应该对扩充开放,对修改封闭。
基于OCP
,利用面向对象中的多态性(Polymorphic),更灵活地处理变更拥抱变化,OCP
可以用抽象和继承、面向接口编程手段实现
SRP
的内容是:
- There should never be more than one reason for a class to change
- 决不要有一个以上的理由修改一个类
LSP
的内容是:
- Subtypes must be substitutable for their base types
- Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it
- 子类必须可以被其基类所代
- 使用指向基类的指针或引用的函数,必须能够在不知道具体派生类对象类型的情况下使用它
ISP
的内容是:
- Clients should not be forced to depend upon interfaces that they do not use
- 客户不应该依赖他们并未使用的接口
DIP
的内容是:
- High level modules should not depend upon low level modules. Both should depend upon abstractions
- Abstractions should not depend upon details. Details should depend upon abstractions
- 高层模块不应该依赖于低层模块。二者都应该依赖于抽象
- 抽象不应该依赖于细节。细节应该依赖于抽象
注意以下5点:
代码:
abstract class Data {
abstract public void DisplayValue(); }class Integer extends Data { int value; Integer() { value=100; } public void DisplayValue(){ System.out.println (value); } } //20135215abstract class Factory { abstract public Data CreateDataObject(); }class IntFactory extends Factory { public Data CreateDataObject(){ return new Integer(); } } //20135215class Document { Data pd; Document(Factory pf){ pd = pf.CreateDataObject(); } public void DisplayData(){ pd.DisplayValue(); } } public class MyDoc { static Document d; public static void main(String[] args) { d = new Document(new IntFactory()); d.DisplayData(); } }(四)实验练习
使用TDD的方式设计关实现复数类Complex。
代码1:
package complex;
public class ComplexTest{
public static void main(String[] args) {
Complex c=new Complex();
Complex c1=new Complex(6,12);
Complex c2=new Complex(11,32);
c1.Output();
c2.Output();
System.out.println("这两复数和为:");
System.out.println(c.add(c1, c2).r+"+"+c.add(c1, c2).i+"i");
System.out.println("这两复数差为:");
System.out.println(c.reduce(c1, c2).r+"+"+c.reduce(c1, c2).i+"i");
}
}
代码2:
package complex;
public class Complex{
double r,i;
Complex()
{
this.r=0;//实数
this.i=0;//复数
}
Complex(double re,double im)
{
this.r=re;
this.i=im;
}
Complex reduce(Complex p1,Complex p2)
{
Complex p =new Complex(p1.r-p2.r,p1.i-p2.i);
return p;
}
Complex add(Complex p1, Complex p2) {
Complex p =new Complex(p1.r+p2.r,p1.i+p2.i);
return p;
}
void Output()
{
System.out.println("复数的值为:");
if(this.i!=0)
System.out.println(this.r+"+"+this.i+"i");
else
System.out.println(this.r);
}
}
实验的好处:
先写出伪代码,可以使在编写产品代码时更加流畅,编写测试代码可以尽量减少产品代码中的bug。因此单元测试可以有效地提高编程效率,减少所写程序中的bug。
实验中遇到的问题:
复数类的定义不了解。
二、实验感想
1、这次实验耗费了很长时间,最后都要做不下去了。我深深体会到网络的重要性和学习新方法、使用新工具的能力的重要性。
2、UML图有点抽象,在虚拟机上实现的时候操作不熟练,刚开始一直没明白怎么把那个框调出来(因为实验楼虚拟机一直出问题,自己没有静下心来看操作步骤上“单击工具栏上的类图标,再在class diagram(类图)中单击一下”),之后是那条箭头画不上去,百度教程,应该是先点击工具栏上的箭头图标(实现关系)然后点击起始的类,出现一条虚线,再点击指向的类。终于把能图画出来了。
3、TDD的方式例题的测试代码看得懂,但是自己编写的时候就不知道哪些语句怎么用,只好用自己写的测试代码,可能这样不算严格TDD方式,但是我觉得这样的思想对我自己设计某些独立功能是有很大帮助的。
4、做练习代码的时候,一看到实现复数类不知道具体是要做什么,就上网搜了一下“Complex”,发现有输出、加法、减法的功能,然后我就按着这样的思路编写了伪代码。开始的时候没有把功能抽取出来,啰嗦的写了很多,然后抽取了print功能,将每一项功能单独出来,代码一下就变少了。
然后我写完上述报告后,看到老师给的复数类还有乘法的功能,我就把代码翻出来,再实现了一下乘法的功能: