zoukankan      html  css  js  c++  java
  • 20175212童皓桢 Java实验二-面向对象程序设计实验报告

    20175212童皓桢 Java实验二-面向对象程序设计实验报告

    实验内容

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

    实验步骤

    (一)单元测试

    • 在IDEA中建一个项目MyUtil
    • 对于MyUtil类,建立一个MyUtilTest1.java的测试类:
    新建一个test文件夹在根目录中->右键选择Mark Directory as->Test Sources Root
    

    输入图片说明
    之后在test文件夹中建立一个MyUtilTest1.java的测试类

    • 在文件中输入如图代码并运行,测试结果如下:

    正常情况
    输入图片说明

    边界情况
    输入图片说明

    异常情况
    输入图片说明

    (二)TDD(Test Driven Devlopment, 测试驱动开发)

    • 按照教程安装Juit和JUnitGenerator V2.0

    • 点击源代码中的类名MyUtil,选择Junit3测试用例,建立一个MyUtilTest测试文件

    • 若TestCase是红色,则引入junit.jar包
      输入图片说明

    • 输入如图测试代码并运行,如果测试失败则出现如图提示
      输入图片说明

    • 根提示据修改源代码,注意边界异常情况,修改完善后测试通过
      输入图片说明

    (三)以TDD方式研究学习StringBuffer

    • 按照老师给出的程序输入
    public static void main(String [] args){
           StringBuffer buffer = new StringBuffer();
           buffer.append('S');
           buffer.append("tringBuffer");
           System.out.println(buffer.charAt(1));
           System.out.println(buffer.capacity());
           System.out.println(buffer.length());
           System.out.println(buffer.indexOf("tring"));
           System.out.println("buffer = " + buffer.toString());
    
    
    • 将方法进行重写,添加返回值,以便于测试
    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 buf) {
            return buffer.indexOf(buf);
        }
    }
    
    
    • 利用API查出并猜测charAt(int i),indexOf(String s),capacity(),length()四种方法的功能。
      输入图片说明
      输入图片说明
      输入图片说明

    • 利用JUnit进行测试,并输入如图测试代码,test passed!
      输入图片说明

    (四)面向对象的三要素

    • 面向对象(Object-Oriented)的三要素包括:封装、继承、多态。面向对象的思想涉及到软件开发的各个方面,如面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程实现(OOP)。OOA根据抽象关键的问题域来分解系统,关注是什么(what)。OOD是一种提供符号设计系统的面向对象的实现过程,用非常接近问题域术语的方法把系统构造成“现实世界”的对象,关注怎么做(how),通过模型来实现功能规范。OOP则在设计的基础上用编程语言(如Java)编码。贯穿OOA、OOD和OOP的主线正是抽象。

    (五)设计模式初步

    • 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,依赖倒置原则)
        • 高层模块不应该依赖于低层模块。二者都应该依赖于抽象
        • 抽象不应该依赖于细节。细节应该依赖于抽象
    • 模式与设计模式
      • 设计模式有四个基本要素:
        • Pattern name:描述模式,便于交流,存档
        • Problem:描述何处应用该模式
        • Solution:描述一个设计的组成元素,不针对特例
        • Consequence:应用该模式的结果和权衡(trade-offs)
    • 其他面对对象原则
      • "组合替代继承":这是说相对于继承,要更倾向于使用组合;
      • "笛米特法则":这是说"你的类对其它类知道的越少越好";
      • "共同封闭原则":这是说"相关类应该打包在一起";
      • "稳定抽象原则":这是说"类越稳定,越应该由抽象类组成";

    (六)对MyDoc类进行扩充,让其支持Byte类,初步理解设计模式

    题目 :对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式,让系统支持Byte类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印

    // 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 Byte extends Data {
        byte value;
        Byte(){
            value=127;
        }
        public void DisplayValue(){
            System.out.println(value);
        }
    }
    abstract class Factory {
        abstract public Data CreateDataObject();
    }
    class IntFactory extends Factory {
        public Data CreateDataObject(){
            return new Integer();
        }
    }
    class ByteFactory extends Factory {
        public Data CreateDataObject(){
            return new Byte();
        }
    }
    class Document {
        Data pd;
        Document(Factory pf){
            pd = pf.CreateDataObject();
        }
        public void DisplayData(){
            pd.DisplayValue();
        }
    }
    public class MyDoc {
        static Document d;
        static Document e;
        public static void main(String[] args) {
            e=new Document(new ByteFactory());
            e.DisplayData();
        }
    }
    
    • 运行结果:
      输入图片说明

    (七)以TDD的方式开发一个复数类Complex

    • 任务:以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)
    
    

    本道练习题基本考察TDD编码的节奏。因为本题中实部虚部很容易混淆,导致出错

    输入图片说明
    因此根据测试代码来修改产品代码的优越性得以体现。

    • 产品代码:
    public class Complex{
        private double a;
        private double b;
    
        public Complex(double a, double b) {
            this.a = a;
            this.b = b;
        }
    
        public static double getRealPart(double a) {
            return a;
        }
    
        public static double getImagePart(double b) {
            return b;
        }
    
        public Complex ComplexAdd(Complex c) {
            return new Complex(a + c.a, b + c.b);
        }
        public Complex ComplexSub(Complex c) {
            return new Complex(a - c.a, b - c.b);
        }
        public Complex ComplexMulti(Complex c) {
            return new Complex(a * c.a - b * c.b, a * c.b + b * c.a);
        }
        public Complex ComplexDiv(Complex c) {
            return new Complex((a * c.b + b * c.a)/(c.b * c.b + c.a * c.a), (b * c.b + a * c.a)/(c.b * c.b + c.a * c.a));
        }
    
        public String toString() {
            String s = " ";
            if (b > 0)
                s =  a + "+" + b + "i";
            if (b == 0)
                s =  a + "";
            if (b < 0)
                s = a + " " + b + "i";
            return s;
        }
    }
    
    
    • 测试代码
    import junit.framework.TestCase;
    import org.junit.Test;
    
    public class ComplexTest extends TestCase {
        Complex c1 = new Complex(0, 2);
        Complex c2 = new Complex(-1, -1);
        Complex c3 = new Complex(1,1);
        @Test
        public void testgetRealPart() throws Exception {
            assertEquals(-3.0, Complex.getRealPart(-3.0));
            assertEquals(3.0, Complex.getRealPart(3.0));
            assertEquals(0.0, Complex.getRealPart(0.0));
        }
        @Test
        public void testgetImagePart() throws Exception {
            assertEquals(-3.0, Complex.getImagePart(-3.0));
            assertEquals(3.0, Complex.getImagePart(3.0));
            assertEquals(0.0, Complex.getImagePart(0.0));
        }
        @Test
        public void testComplexAdd() throws Exception {
            assertEquals("-1.0+1.0i", c1.ComplexAdd(c2).toString());
            assertEquals("1.0+3.0i", c1.ComplexAdd(c3).toString());
            assertEquals("0.0", c2.ComplexAdd(c3).toString());
        }
        @Test
        public void testComplexSub() throws Exception {
            assertEquals("1.0+3.0i", c1.ComplexSub(c2).toString());
            assertEquals("-1.0+1.0i", c1.ComplexSub(c3).toString());
            assertEquals("-2.0 -2.0i", c2.ComplexSub(c3).toString());
        }
        @Test
        public void testComplexMulti() throws Exception {
            assertEquals("2.0 -2.0i", c1.ComplexMulti(c2).toString());
            assertEquals("-2.0+2.0i", c1.ComplexMulti(c3).toString());
            assertEquals("0.0 -2.0i", c2.ComplexMulti(c3).toString());
        }
        @Test
        public void testComplexComplexDiv() throws Exception {
            assertEquals("-1.0 -1.0i", c1.ComplexDiv(c2).toString());
            assertEquals("1.0+1.0i", c1.ComplexDiv(c3).toString());
            assertEquals("-1.0 -1.0i", c2.ComplexDiv(c3).toString());
        }
    
    }
    
    
    • 运行结果截图
      输入图片说明

    (八)对实验二中的代码进行建模

    • 代码如下:
    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() + "!";
        }
    }
    
    
    
    • 创建的UML类图

    输入图片说明

    实验中遇到的问题

    • 问题一:包名Junit提示错误
      输入图片说明
    • 解决办法一:参考同学的博客,摸索出方法,具体如下:
    File -> Project Struct... -> Libraies -> 点击加号 -> Java -> 选择IDEA目录下的Lib中的junit-4.12 ->选择ok
    

    输入图片说明

    另外的,如果当时安装是通过Toolbox,IDEA的安装目录则很有可能被隐藏,因此需搜索junit-4.12找到具体路径后,在管理员权限下解除隐藏才能选择。
    输入图片说明

    • 问题二:单元测试时提示找不到main方法。
      输入图片说明

    • 解决办法二: 尝试修改测试类名与JUnit测试类名不同,即可解决。
      输入图片说明

    感悟和体会

    • 利用API可以查询并学习使用一些功能强大的类和方法。
    • 并跟随TDD方法的节奏设计出伪代码、产品代码和测试代码,有利于自己的程序除了正确性,在更高层面不容易出错
    • 之后可以考虑更加改善测试单元的写法,比如测试例子由计算机穷举生成。

    参考博客

    https://www.cnblogs.com/Vivian517/p/6741501.html#YI

  • 相关阅读:
    蓝桥杯 网络寻路
    ny33 蛇形填数
    集合运算 蓝桥杯 set容器
    蓝桥杯 回形取数
    bam/sam格式说明--转载
    samtools一些文档
    Linux批量更改文件后缀-转载
    GATK--使用转载
    Linux下wget下载整个FTP目录(含子目录)--转载
    CRLF line terminators导致shell脚本报错:command not found --转载
  • 原文地址:https://www.cnblogs.com/thz666/p/10717261.html
Copyright © 2011-2022 走看看