zoukankan      html  css  js  c++  java
  • # 20155219实验二 Java面向对象程序设计

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

    一、实验内容

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

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

    3.初步掌握UML建模

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

    5.了解设计模式

    二、实验步骤

    (一)单元测试

    (1) 三种代码

    1.伪代码:以简洁的自然语言表明设计步骤;伪代码是产品代码最自然的、最好的注释。

    百分制转五分制:
       如果成绩小于60,转成“不及格”
       如果成绩在60与70之间,转成“及格”
       如果成绩在70与80之间,转成“中等”
       如果成绩在80与90之间,转成“良好”
       如果成绩在90与100之间,转成“优秀”
       其他,转成“错误”
    

    2.产品代码:用以实现特定功能的程序或机器语言。

    package exp1;
    public class MyUtil{
       public static String percentage2fivegrade(int grade){
       //如果成绩小于60,转成“不及格”
       if (grade < 60)
           return "不及格";
       //如果成绩在60与70之间,转成“及格”
       else if (grade < 70)
           return "及格";
       //如果成绩在70与80之间,转成“中等”
       else if (grade < 80)
           return "中等";
       //如果成绩在80与90之间,转成“良好”
       else if (grade < 90)
           return "良好";
       //如果成绩在90与100之间,转成“优秀”
       else if (grade < 100)
           return "优秀";
       //其他,转成“错误”
       else 
           return "错误";
       }
    }
    

    3.测试代码:用以对产品代码进行测试的代码。

    • 测试一:选取某一合法输入值进行测试
    public class MyUtilTest {
    public static void main(String[] args) {
        // 百分制成绩是50时应该返回五级制的“不及格”
        if(MyUtil.percentage2fivegrade(50) != "不及格")
            System.out.println("test failed!");
        else 
            System.out.println("test passed!");
    }
    }
    

    测试结果如下
    image

    • 测试二:全面覆盖各等级段
    public class MyUtilTest {
    public static void main(String[] args) {
        //测试正常情况
        if(MyUtil.percentage2fivegrade(55) != "不及格")
            System.out.println("test failed!");
        else if(MyUtil.percentage2fivegrade(65) != "及格")
            System.out.println("test failed!");
        else if(MyUtil.percentage2fivegrade(75) != "中等")
            System.out.println("test failed!");
        else if(MyUtil.percentage2fivegrade(85) != "良好")
            System.out.println("test failed!");
        else if(MyUtil.percentage2fivegrade(95) != "优秀")
            System.out.println("test failed!");
        else 
            System.out.println("test passed!");
    }
    }
    

    运行结果如下:
    image

    • 测试三:异常情况测试
    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!");
    }
    }
    

    运行结果如下:image
    出现此错误的 原因是判断不及格时没有要求成绩大于零,因此需要增加对负分的判断:

    public class MyUtil{
       public static String percentage2fivegrade(int grade){
           //如果成绩小于0,转成“错误”
           if ((grade < 0))
               return "错误";
           //如果成绩小于60,转成“不及格”
           else if (grade < 60)
               return "不及格";
           //如果成绩在60与70之间,转成“及格”
           else if (grade < 70)
               return "及格";
           //如果成绩在70与80之间,转成“中等”
           else if (grade < 80)
               return "中等";
           //如果成绩在80与90之间,转成“良好”
           else if (grade < 90)
               return "良好";
           //如果成绩在90与100之间,转成“优秀”
           else if (grade < 100)
               return "优秀";
           //如果成绩大于100,转成“错误”
           else
               return "错误";
       }
    }
    

    之后再次运行程序:image
    程序通过编译正确运行。

    • 测试四:测试分段结点
      我们对输入为“0,60,70,80,90,100”这些边界情况进行测试的代码如下:
    public class MyUtilTest {
        public static void main(String[] args) {
            //测试边界情况
            if(MyUtil.percentage2fivegrade(0) != "不及格")
                System.out.println("test failed 1!");
            else if(MyUtil.percentage2fivegrade(60) != "及格")
                System.out.println("test failed 2!");
            else if(MyUtil.percentage2fivegrade(70) != "中等")
                System.out.println("test failed 3!");
            else if(MyUtil.percentage2fivegrade(80) != "良好")
                System.out.println("test failed 4!");
            else if(MyUtil.percentage2fivegrade(90) != "优秀")
                System.out.println("test failed 5!");
            else if(MyUtil.percentage2fivegrade(100) != "优秀")
                System.out.println("test failed 6!");
            else 
                System.out.println("test passed!"); 
        }
    

    TDD研究方式

    TDD的一般步骤如下:

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

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

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

    编写产品代码

    测试通过

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

    循环完成所有功能的开发

    以 TDD的方式研究学习StringBuffer

    • 源代码如下:
    public class StringBufferDemo {
        public static String append1(StringBuffer a,String b)
        {
            return a.append(b).toString();
        }
        public  static char charAt1(StringBuffer a,int i)
        {
            return a.charAt(i);
        }
        public  static int capacity1(StringBuffer a)
        {
            return a.capacity();
        }
        public static int indexof(StringBuffer a,String b)//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
        {
            return a.indexOf(b);
        }
        public static int length1(StringBuffer a)
        {
            return a.length();
        }
    }
    
    
    • 测试代码如下:
    import junit.framework.TestResult;
    import org.junit.Test;
    import junit.framework.TestCase;
    public class StringBufferDemoTest extends TestCase {
        StringBuffer buffer = new StringBuffer(20);
        @Test
        public void testNormal() {
            assertEquals("String",StringBufferDemo.append1(buffer,"String"));
            assertEquals('r',StringBufferDemo.charAt1(buffer,2));
            assertEquals(20,StringBufferDemo.capacity1(buffer));
            assertEquals(1,StringBufferDemo.indexof(buffer,"tring"));
            assertEquals(6,StringBufferDemo.length1(buffer));
        }
    }
    

    Java面向对象程序设计

    • 对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式。
    • 让系统支持Short类,并在MyDoc类中添加测试代码表明添加正确。

    代码如下所示:

    import java.lang.*;
    // Server Classes
    abstract class Data {
        abstract public void DisplayValue();
    }
    class Integer extends  Data {
        int value;
        Integer() {
            value=100;
        }
        public void DisplayValue(){
            System.out.println (value);
        }
    }
    class Short extends Data{
        short  value;
        Short()
        {
            value=100;
        }
        public void DisplayValue(){
            System.out.println(value);
        }
    }
    // Pattern Classes
    abstract class Factory {
        abstract public Data CreateDataObject();
    }
    class IntFactory extends Factory {
        public Data CreateDataObject(){
            return new Integer();
        }
    }
    class ShortFactory extends Factory{
        public Data CreateDataObject()
        {
            return new Short();
        }
    }
    //Client classes
    class Document {
        Data pd;
        Document(Factory pf){
            pd = pf.CreateDataObject();
        }
        public void DisplayData(){
            pd.DisplayValue();
        }
    }
    //Test class
    public class MyDoc {
        static Document d;
        public static void main(String[] args) {
            d = new Document(new ShortFactory());
            d.DisplayData();
        }
    }
    

    其中包含了老师给的支持Integer()类,和字节编写的支持short()类。
    运行结果如下图:image

    练习

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

    1.伪代码:

    Complex类要输出实部,输出虚部,并按照a+bi的形式输出复数。
    Complex类中有两个变量,实部RealPart和虚部ImaginePart;
    
    方法:
    getRealPart(int RealPart);返回实部
    getImaginePart(int ImaginePart);返回虚部
    add(Complex c);实现复数相加
    minus(Complex c);实现复数相减
    multiply(Complex c);实现复数相乘
    toString(int RealPart,int ImaginePart);将复数输出成a+bi的格式。
    

    最终代码:

    public class MyComplex {
        private double m;
        private double n;
        public double getm(double m)
        {
            return m;
        }
        public double getn(double n)
        {
            return n;
        }
        public void setm(double m)
        {
            this.m=m;
        }
        public void setn(double n)
        {
            this.n=n;
        }
        public MyComplex(double m, double n) {
            this.m = m;
            this.n = n;
        }
        public MyComplex add(MyComplex c) {
            return new MyComplex(m + c.m, n + c.n);
        }
        public MyComplex minus(MyComplex c) {
            return new MyComplex(m - c.m, n - c.n);
        }
        public MyComplex multiply(MyComplex c) {
            return new MyComplex(m * c.m - n * c.n, m * c.n + n * c.m);
        }
        public MyComplex  ComplexDiv(MyComplex c)
        {
            return new MyComplex((m*c.m+n*c.n)/((c.m*c.m)*(c.n*c.n)),(n*c.m-m*c.n)/((c.m*c.m)*(c.n*c.n)));
        }
        public String toString() {
            String str = new String();
            if (this.n>=0)
            {
                str=m+"+"+n+"i";
            }
            else str=m+"-"+(-n)+"i";
            return str;
        }
        public boolean equals(MyComplex c)
        {
            if(this.m==c.m&&this.n==c.n)
                return true;
            else
                return false;
        }
    }
    

    测试代码:

    public class MyComplexTest extends TestCase {
        MyComplex a = new MyComplex(1, 2);
        MyComplex b = new MyComplex(1, -4);
        MyComplex c = new MyComplex(19, 0);
        MyComplex d = new MyComplex(0, -3);
        MyComplex e = new MyComplex(1, 0);
        MyComplex f = new MyComplex(1, 0);
        @Test
        public void testadd()
        {
            assertEquals("2.0-2.0i",a.add(b).toString());
            assertEquals("1.0-1.0i",a.add(d).toString());
        }
        @Test
        public void testminus()
        {
            assertEquals("0.0+6.0i", a.minus(b).toString());
            assertEquals("-18.0+2.0i", a.minus(c).toString());
        }
        @Test
        public void testmultiply()
        {
            assertEquals("9.0-2.0i", a.multiply(b).toString());
            assertEquals("19.0+38.0i", a.multiply(c).toString());
        }
        @Test
        public void testComplexDiv()
        {
            assertEquals("-0.4375+0.375i",a.ComplexDiv(b).toString());
            assertEquals("1.1875+4.75i",c.ComplexDiv(b).toString());
        }
        @Test
        public void testequals()
        {
            assertEquals(false,a.equals(b));
            assertEquals(true,e.equals(f));
        }
    }
    

    利用StarUML软件进行UML建模

    image将生成代码稍作修改,可以得到输出如下:image

    实验总结与体会

    这一次的实验我学会了如何使用单元测试,单元测试不仅能保证项目进度还能优化我们的设计,我们可以从测试中发现一些设计时所遗漏的问题,从而改善自己的代码,测试说到底其实也就是一个发现BUG的过程,我们没有必要对一些能够肯定正确的答案进行测试,相反,我们要尽可能把那些觉得容易出错的答案进行测试,这样也就能够更快的发现BUG的所在。

    PSP(Personal Software Process)时间

    步骤 耗时 百分比
    需求分析 15min 12.5%
    设计 15min 12.5%
    代码实现 60min 50.0%
    测试 15min 12.5%
    分析总结 15min 12.5%

    参考资料

  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/paypay/p/6746321.html
Copyright © 2011-2022 走看看