20165235 Java面向对象程序设计
- 姓名:祁瑛
- 学号:20165235
- 班级:1652
- 实验课程:JAVA程序设计
- 实验名称:Java面向对象程序设计
- 实验时间:2018.4.14
- 指导老师:娄家鹏
一,实验内容及步骤
面向对象程序设计-1
- 单元测试:这里我们设计了一个测试用例
(Test Case)
,测试用例是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。在运行程序时可以找到bug。 - 在本次实验中我的产品代码如下:
public class MyUtil1{ 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 "错误"; }}
- 测试代码: 1.正常情况:
public class MyUtilTest { public static void main(String[] args) { //测试正常情况 if(MyUtil.percentage2fivegrade(55) != "不及格") System.out.println("test failed 1!"); else if(MyUtil.percentage2fivegrade(65) != "及格") System.out.println("test failed 2!"); else if(MyUtil.percentage2fivegrade(75) != "中等") System.out.println("test failed 3!"); else if(MyUtil.percentage2fivegrade(85) != "良好") System.out.println("test failed 4!"); else if(MyUtil.percentage2fivegrade(95) != "优秀") System.out.println("test failed 5!"); } }
- 测试图: 2.非正常情况测试代码:
public class MyUtilTest { public static void main(String[] args) {//测试出错情况 if(MyUtil.percentage2fivegrade(-10) != "错误") System.out.println("test failed 1!"); else if(MyUtil.percentage2fivegrade(115) != "错误") System.out.println("test failed 2!"); else System.out.println("test passed!"); }}
- 测试图:
Java中有单元测试工具JUnit来辅助进行TDD,我们用TDD的方式把前面百分制转五分制的例子重写一次。
- TDD的测试步骤如下:
- 明确当前要完成的功能,记录成一个测试列表
- 快速完成编写针对此功能的测试用例
- 测试代码编译不通过(没产品代码呢)
- 编写产品代码
- 测试通过
- 对代码进行重构,并保证测试通过(重构下次实验练习)
- 循环完成所有功能的开发
- 以下是测试代码:
import org.junit.Test;import junit.framework.TestCase;public class MyUtilTest extends TestCase { @Test public void testNormal() { assertEquals("不及格", MyUtil1.percentage2fivegrade(55)); assertEquals("及格", MyUtil1.percentage2fivegrade(65)); assertEquals("中等", MyUtil1.percentage2fivegrade(75)); assertEquals("良好", MyUtil1.percentage2fivegrade(85)); assertEquals("优秀", MyUtil1.percentage2fivegrade(95)); } @Test public void testAbnormal() { assertEquals("错误", MyUtil1.percentage2fivegrade(-55)); assertEquals("错误", MyUtil1.percentage2fivegrade(155)); } @Test public void testBorder() { assertEquals("不及格", MyUtil1.percentage2fivegrade(0)); assertEquals("及格", MyUtil1.percentage2fivegrade(60)); assertEquals("中等", MyUtil1.percentage2fivegrade(70)); assertEquals("良好", MyUtil1.percentage2fivegrade(80)); assertEquals("优秀", MyUtil1.percentage2fivegrade(90)); assertEquals("优秀", MyUtil1.percentage2fivegrade(100)); }}
测试图如下:
当JUnit出现绿条说明测试成功。
面向对象程序设计-2
- 对于这个程序,需要测试的方法有四个,
charAt()、capacity()、length()、indexOf
。而且要对老师博客中给出的代码进行改写,对测试的方法要加上返回值,便于我们测试。 -以下是TDD的方式研究学习StringBuffer
public class StringBufferDemo{ StringBuffer buffer = new StringBuffer(); public StringBufferDemo(StringBuffer buffer){ this.buffer = buffer; } public Character charAt(int i){ return buffer.charAt(i); } public int capacity(){ return buffer.capacity(); } public int length(){ return buffer.length(); } public int indexOf(String str) { return buffer.indexOf(str); }}
- 而且有必要了解以下上面四个方法的作用:
- charAt(int n):返回指定字符在字符串中的位置。
- indexOf(String s):返回输入的子字符串的第一个字母在母字符串的位置
- capacity():是当前实体的实际容量。
- length():实体中存放的字符序列的长度。
- 有了初步的了解后就可以进行测试了,以下是测试代码:
import junit.framework.TestCase; import org.junit.Test;public class StringBufferDemoTest extends TestCase { StringBuffer str1 = new StringBuffer("StringBuffer"); StringBuffer str2 = new StringBuffer("StringBufferStringBuffer"); StringBuffer str3 = new StringBuffer("StringBufferStringBufferStringBuffer"); @Test public void testcharAt() throws Exception{ assertEquals('S',str1.charAt(0)); assertEquals('g',str1.charAt(5)); assertEquals('r',str1.charAt(11)); } @Test public void testcapacity() throws Exception{ assertEquals(28,str1.capacity()); assertEquals(40,str2.capacity()); assertEquals(52,str3.capacity()); } @Test public void testlength() throws Exception{ assertEquals(12,str1.length()); assertEquals(24,str2.length()); assertEquals(36,str3.length()); } @Test public void testindexOf() throws Exception{ assertEquals(0,str1.indexOf("Str")); assertEquals(5,str2.indexOf("gBu")); assertEquals(10,str3.indexOf("er")); }}
- 以下是测试图:
面向对象程序设计-3
设计应该满足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,依赖倒置原则)
- 老师给出的代码是实现返回int类,题目要求给出返回long类,如果对代码直接进行删改就违反了OCP原则,对增加开放,对删除封闭。所以要使用设计模式了。使用面向接口编程,使用抽象和继承。以下是实验任务:
- 用自己的学号%6进行取余运算,根据结果进行代码扩充:
- 0: 让系统支持Byte类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 1: 让系统支持Short类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 2: 让系统支持Boolean类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 3: 让系统支持Long类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 4: 让系统支持Float类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 5: 让系统支持Double类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 对代码只需要增加
class Long extends Data
、class LongFactory extends Factory
即可使系统支持Long类型。以下是测试代码:
abstract class Data{ public abstract void DisplayValue();}class Integer extends Data { int value; Integer(){ value=100; } public void DisplayValue(){ System.out.println(value); }}class Long extends Data { long value; Long(){ value=20165235l; } public void DisplayValue(){ System.out.println(value); }}class Float extends Data { float value; Float(){ value=2.0165235F; } public void DisplayValue(){ System.out.println(value); }}class Document { Data pd; Document(Factory pf){ pd = pf.CreateDataObject(); } public void DisplayData(){ pd.DisplayValue(); }}abstract class Factory { abstract public Data CreateDataObject();}class IntFactory extends Factory { public Data CreateDataObject(){ return new Integer(); }}class LongFactory extends Factory { public Data CreateDataObject(){ return new Float(); }}class FloatFactory extends Factory { public Data CreateDataObject(){ return new Float(); }}public class MyDoc { static Document d; public static void main(String[] args) { d = new Document(new FloatFactory()); d.DisplayData(); }}
- 而且我在程序里不仅实现返回long类而且实现了返回Float类,步骤如同上。
测试图:
- 而且我使用了starMUL软件对本次程序代码进行建模。使用程序步骤如下:
- 首先打开starMUL,如下图点击
- 在左侧的ToolBox中选择画图工具
- 在右侧的文件管理中可以进行删除等操作
这次实验的MUL图:
面向对象程序设计-4
- 本次实验任务:
使用TDD的方式设计关实现复数类Complex
// 定义属性并生成getter,setter
double RealPart; double ImagePart; // 定义构造函数 public Complex() public Complex(double R,double I) //Override Object public boolean equals(Object obj) public String toString() // 定义公有方法:加减乘除 Complex ComplexAdd(Complex a) Complex ComplexSub(Complex a) Complex ComplexMulti(Complex a) Complex ComplexDiv(Complex a) ---首先应该是写伪代码:
在Complex类中设置构造方法public Complex()
public Complex(double R,double I) 设置实部与虚部double RealPart; double ImagePart; 设置返回实部与虚部的方法 实现加法Complex ComplexAdd(Complex a) 实现减法Complex ComplexSub(Complex a) 实现乘法Complex ComplexMulti(Complex a) 实现除法Complex ComplexDiv(Complex a) 重写toString()方法 重写equals()方法- 有了伪代码就可以写产品代码了:
public class Complex { double R;//复数的实部 double I;//复数的虚部 Complex(double R, double I) { this.R = R; this.I = I; } public static double getRealPart(double R) { //返回复数的实部 return R; } public static double getImagePart(double I) { //返回复数的虚部 return I; } public Complex ComplexAdd(Complex c) {//加法运算 return new Complex(R + c.R, I + c.I); } public Complex ComplexSub(Complex c) {//减法运算 return new Complex(R - c.R, I - c.I); } public Complex ComplexMulti(Complex c) {//乘法运算 return new Complex(R * c.R - I * c.I, R * c.I + I * c.R); } public Complex ComplexDiv(Complex c) {//除法运算 return new Complex((R * c.I + I * c.R) / (c.I * c.I + c.R * c.R), (I * c.I + R * c.R) / (c.I * c.I + c.R * c.R)); } public String toString() {//重写toString方法 String str = ""; if (I > 0) str = R + "+" + I + "i"; if (I == 0) str = R+""; if (I < 0) str = R + "" + I + "i"; return str; } public boolean equals(Object obj){//重写equals方法 if (this == obj) return true; if(obj==null) return false; if(obj instanceof Complex){ Complex p = (Complex) obj; if(p.R==this.R &&p.I==this.I ) return true; } return false; }}
- 以下是测试代码:
import junit.framework.TestCase;import org.junit.Test;public class ComplexTestTest extends TestCase { Complex c1 = new Complex(1.0,2.0); Complex c2 = new Complex(2.0,2.0); Complex c3 = new Complex(2.0,0.0); @Test public void testGetRealPart() throws Exception { assertEquals(-1.1, Complex.getRealPart(-1.1)); assertEquals(6.0, Complex.getRealPart(6.0)); assertEquals(0.0, Complex.getRealPart(0.0)); } @Test public void testGetImagePart() throws Exception { assertEquals(-1.1, Complex.getImagePart(-1.1)); assertEquals(6.0, Complex.getImagePart(6.0)); assertEquals(0.0, Complex.getImagePart(0.0)); } @Test public void testComplexAdd() throws Exception { assertEquals("3.0+4.0i", c1.ComplexAdd(c2).toString()); assertEquals("3.0+2.0i", c1.ComplexAdd(c3).toString()); assertEquals("4.0+2.0i", c2.ComplexAdd(c3).toString()); } @Test public void testComplexSub() throws Exception { assertEquals("-1.0", c1.ComplexSub(c2).toString()); assertEquals("-1.0+2.0i", c1.ComplexSub(c3).toString()); assertEquals("0.0+2.0i", c2.ComplexSub(c3).toString()); } @Test public void testComplexMulti() throws Exception { assertEquals("-2.0+6.0i", c1.ComplexMulti(c2).toString()); assertEquals("2.0+4.0i", c1.ComplexMulti(c3).toString()); assertEquals("4.0+4.0i", c2.ComplexMulti(c3).toString()); } @Test public void testComplexComplexDiv() throws Exception { assertEquals("0.75+0.75i", c1.ComplexDiv(c2).toString()); assertEquals("1.0+0.5i", c1.ComplexDiv(c3).toString()); assertEquals("1.0+1.0i", c2.ComplexDiv(c3).toString()); } @Test public void testEquals() throws Exception{ assertEquals(false,c1.equals(c2)); assertEquals(false,c1.equals(c3)); assertEquals(false,c2.equals(c3)); assertEquals(true,c1.equals(c1)); }}
- 测试图如下:
实验过程中遇到的问题及解决
- 问题一:使用ieda时显示无法加载到主类:
如图:
解决方法:点右上方的
main
,:
-点Edit configurations
, 把Name和Main class名称改了就行。
- 问题二:
junit
包导入了,为什么@Test还是红的 - 解决方法:点击代码旁的小灯泡然后点击
Convert to Junit4 Test case
- 问题三:一直找不到
JunitGeneratorV2.0
的下载路径 - 解决方法:打开plugins,点击下面的browse
- 然后检索Junit就可以找出来
- 问题四:一直找不到junit的路径。
解决方法:可以直接在盘里搜关键字
junit
就可以搜出来。实验感想
- 本周的实验比较多但主旨相对集中:面向对象编程和TDD的使用。对于面向对象编程要满足三要素:封装,继承与多态。想要更好的了解这些属性我感觉灵活的使用starMUL建模是个不错的方法。灵活的使用设计模式也很重要,对于设计模式要满足S.O.L.I.D原则,本次着重学习的是S.O.L.I.D中的OCP原则。设计完程序后又要新的需求但是不能删改代码,这里就要使用到设计模式,对增加代码开放,对删改进行封闭,这一原则不仅有益于实现需求,更能减少程序的bug。在Java语言中,可以通过JUnit框架进行单元测试,通过单元测试可以减少代码的bug,提高代码的质量。
-
步骤 耗时 百分比 需求分析 20min 8% 设计 60min 25% 代码实现 120min 50% 测试 10min 4% 分析总结 30min 13%