软件构造-实验三-仅供参考
姓名 |
|
学号 |
|
班号 |
|
电子邮件 |
|
手机号码 |
|
目录
1 实验目标概述···· 1
2 实验环境配置···· 1
3 实验过程···· 1
3.1 待开发的三个应用场景··· 1
3.2 基于语法的图数据输入··· 1
3.3 面向复用的设计:CircularOrbit<L,E>· 1
3.4 面向复用的设计:Track· 2
3.5 面向复用的设计:L· 2
3.6 面向复用的设计:PhysicalObject· 2
3.7 可复用API设计···· 2
3.8 图的可视化:第三方API的复用···· 2
3.9 设计模式应用···· 2
3.10 应用设计与开发···· 2
3.10.1 TrackGame· 2
3.10.2 StellarSystem· 2
3.10.3 AtomStructure· 2
3.10.4 PersonalAppEcosystem· 2
3.10.5 SocialNetworkCircle· 2
3.11 应对应用面临的新变化···· 2
3.11.1 TrackGame· 3
3.11.2 StellarSystem· 3
3.11.3 AtomStructure· 3
3.11.4 PersonalAppEcosystem· 3
3.11.5 SocialNetworkCircle· 3
3.12 Git仓库结构··· 3
4 实验进度记录···· 3
5 实验过程中遇到的困难与解决途径···· 3
6 实验过程中收获的经验、教训、感想··· 4
6.1 实验过程中收获的经验和教训··· 4
6.2 针对以下方面的感受···· 4
1 实验目标概述
本次实验覆盖课程第 3、5、6 章的内容,目标是编写具有可复用性和可维护 性的软件,主要使用以下软件构造技术: ⚫ 子类型、泛型、多态、重写、重载 ⚫ 继承、代理、组合 ⚫ 常见的 OO 设计模式 ⚫ 语法驱动的编程、正则表达式 ⚫ 基于状态的编程 ⚫ API 设计、API 复用 本次实验给定了五个具体应用(径赛方案编排、太阳系行星模拟、原子结构 可视化、个人移动 App 生态系统、个人社交系统),学生不是直接针对五个应用 分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其 实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可 复用性)和更容易面向各种变化(可维护性)。
2 实验环境配置
安装jdk 随意选择目录 只需把默认安装目录 \java 之前的目录修改即可
安装jre→更改→ \java 之前目录和安装 jdk 目录相同即可
安装完JDK后配置环境变量 计算机→属性→高级系统设置→高级→环境变量
系统变量→新建 JAVA_HOME 变量 。
变量值填写jdk的安装目录
系统变量→寻找 Path 变量→编辑
在变量值最后输入 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
系统变量→新建 CLASSPATH 变量
变量值填写 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意最前面有一点)
系统变量配置完毕
3 实验过程
3.1 待开发的三个应用场景
首先请列出你要完成的具体应用场景(至少3个,1和2中选一,3必选,4和5中选一,鼓励完成更多的应用场景)。
l StellarSystem
l AtomStructure
l SocialNetworkCircle
共性:
- 需要轨道中存在的对象,包括轨道,中心物体,轨道物体。其中物体不需要考虑绝对位置。
- 需要完成的功能有:添加和删除轨道,添加和删除物体,获得轨道系统的熵值,获得距离,差异。检查轨道系统的合法性,并且需要可视化。
差异:
- 对象不同,需要实现的具体功能不同。AtomStructure对象都一样知识位置不同。
3.2 基于语法的图数据输入
StellerSystem:
Center使用的是“Stellar\\s*::=\\s*<([A-Za-z]+),(\\d+),(\\d+)>”
star使用的是”Planet\\s*::=\\s*<([A-Za-z]+),( \\d[A-Za-z]+),(\\d [A-Za-z]+),(\\d+),(\\d+),(\\d+),(\\d+),([A-Za-z]+),(\\d+)>”
AtomStructure:
Name使用的是“ElementName\\s*::=\\s*([A-Z]{1}[a-z]{0,1})”
Pattern使用的是”NumberOfTracks\\s*::=\\s*(\\d+)”
Elepattern使用的是“NumberOfElectron\\s*::=\\s*([\\d+\\/\\d+,;]+)”
SocialNetworkCircle:
Cenpattern使用的是”CentralUser\\s*::=\\s*<([A-Za-z0-9]+),\\s*(\\d+),\\s*([MF])>”
Friendpattern使用的是”Friend\\s*::=\\s*<([A-Za-z0-9]+),\\s*(\\d+),\\s*([MF])>”
Socialpattern使用的是“SocialTie\\s*::=\\s*<([A-Za-a0-9]+),\\s*([A-Za-z0-9]+),\\s*([01](?:\\,{1}\\d[1,3]){0,1})>”
3.3 面向复用的设计:CircularOrbit<L,E>
public void setCircularOrbit
设置轨道上物体与中心点物体的中相信轨道关系
public void addtrack
增加一条轨道,向轨道域中添加
public void deletetrack
删除轨道,在轨道域中删除
public void addcenter
增加一个中心点,将中心点设置成LIST即可实现这项功能
public void addstar
辅助功能,添加一个物体
public void addcontactCandS
添加中心物体与轨道上物体的关系
public void addcontactSandS
添加轨道物体与轨道物体之间的关系
3.4 面向复用的设计:Track
类的域:
String name;
这是轨道上物体的名字
double radius;
轨道的半径
构造器:
public Track(String temp,double size)
将name和radius初始化
所用到的方法:
public void setname
设置轨道上物体的名字
public void setradius
设置轨道的半径
public String getname
获取轨道上物体的名字,有检查是否符合规定
public double getradius
获取轨道的半径,有检查是否符合规定
检查:
CheckRep:
assert this.name!=null&&this.radius!=0;
因为名字和轨道半径不能为空,所以在获取名字和半径的时候应道有检查
3.5 面向复用的设计:L
作为中心物体的复用,运用到了抽象技术。为所有中心子类提供了一个父类,可以放在一个接口中。
3.6 面向复用的设计:PhysicalObject
也是作为轨道物体的一个复用,运用抽象,每一个具体引用都继承自这个类,最主要的功能就是提供一个父类。
3.7 可复用API设计
double getObjectDistributionEntropy
计算轨道系统的熵值,在每一个应用中实现。
int getLogicalDistance
计算逻辑距离,同上。
double getPhysicalDistance
计算物理距离,同上。
Difference getDifference
获取差异性,同上
Difference类:
类中域:
所有有可能发生差异的都要声明两份。
方法:
public Difference
构造器,将有可能发生差异的部分都进行初始化
public String getdifference()
将差异用string返回。
3.8 图的可视化:第三方API的复用
StellerSystem:
Star类:
是中心的星球继承了JPanel类,重写了
protected void paintComponent(Graphics g)
并且写了绘制中心点的函数
public void draw(Graphics g)
Stars类:
是轨道上的星球类。
该类继承子Star类,重写了
protected void paintComponent(Graphics g)
画出来中心点,并且绘制椭圆形轨道,颜色调成红色。
public void move()
点运行的函数
public void start()
开始运行
public void pause()
暂停运行
public void accelerate()
加速
public void decelerate()
减速
CircularOrbitHelper类:
是运行GUI的函数,其中包括设置位置,调用函数,设置层的位置,将按钮绑定函数。
AtomStructure:
CircularOrbitHelper类:
定义点并且绘制图像并且运行的主函数。
重写了public void paintComponent(Graphics g),运行绘制点的方法,并且绘制圆形。
public void draw(Graphics g)方法绘制点。
SocialNetworkCircle:
CircularOrbitHelper类:
定义点并且绘制图像并且运行的主函数。
重写了public void paintComponent(Graphics g),运行绘制点的方法,并且绘制圆形。
public void draw(Graphics g)方法绘制点。
public void drawline(Graphics g)两个坐标点之间绘制直线
3.9 设计模式应用
运用了静态方法与内部类结合的方法实现的工程。
3.10 应用设计与开发
3.10.1 TrackGame
3.10.2 StellarSystem
类内域:
static List<PhysicalStarObject> list=new ArrayList<PhysicalStarObject>();
static Map<List<CentralStarObject>, List<PhysicalStarObject>> map=new HashMap<List<CentralStarObject>, List<PhysicalStarObject>>();
static CentralStarObject center = null;
static List<CentralStarObject> wocao=new ArrayList<CentralStarObject>();
static List<Track> track=new ArrayList<Track>();
static int cout=0;
使用的方法:
public void addtrack(PhysicalStarObject star1)
public void deletetrack(PhysicalStarObject star1)
public void addcenter(CentralStarObject center1)
public void addstar(PhysicalStarObject star1)
public void addcontactCandS(CentralStarObject center1, PhysicalStarObject stars1)
public void addcontactSandS(PhysicalStarObject stars1, PhysicalStarObject stars2)
public void setCircularOrbit(CentralStarObject center1, PhysicalStarObject stars1)
double getObjectDistributionEntropy
int getLogicalDistance (CircularOrbit c, PhysicalStarObject e1, PhysicalStarObject e2)
double getPhysicalDistance (CircularOrbit c, PhysicalStarObject e1, PhysicalStarObject e2)
Difference getDifference (PhysicalStarObject c1, PhysicalStarObject c2)
Test:
3.10.3 AtomStructure
类内域:
static List<CenterAtomObject> center= new ArrayList<CenterAtomObject>();
static List<AtomObject> list=new ArrayList<AtomObject>();
static List<Track> track=new ArrayList<Track>();
static Map<Integer, Integer> map=new HashMap<Integer, Integer>();//轨道对应电子数
static Map<CenterAtomObject, Map<Integer, Integer>> atomMap=new HashMap<CenterAtomObject, Map<Integer,Integer>>();
static CenterAtomObject centerAtomObject=null;
static String name;
static int tracksnumber;
static int tracklist;
static int atomnumber;
static int cout=0;
static String[] read;
使用的方法:
public void Transition(int track1,int number,int track2)电子跃迁
double getObjectDistributionEntropy(P2.CircularOrbit c)
int getLogicalDistance(P2.CircularOrbit c, AtomObject e1, AtomObject e2)
double getPhysicalDistance (P2.CircularOrbit c, AtomObject e1, AtomObject e2)
P2.Difference getDifference (AtomObject c1, AtomObject c2)
test:
3.10.4 PersonalAppEcosystem
3.10.5 SocialNetworkCircle
类内域:
static Map<Map<Label, Label>, Double> map=new HashMap<Map<Label,Label>, Double>();//关系图
static Map<Label, Label> col=new HashMap<Label, Label>();
static CentralSocialObject center;
static SocialObject center1;
static List<CentralSocialObject> vista=new ArrayList<CentralSocialObject>();
static List<SocialObject> list=new ArrayList<SocialObject>();//friend
static List<SocialTie> vox=new ArrayList<SocialTie>();//关系
static List<String> a[] = new ArrayList[100];
static int i=2;
static int cout=0;
内部类:
SocialTie是用来记录了两个人之间的关系的内部类。
使用的方法:
public void addcenter(CentralSocialObject temp)
public void deletelist(int i)
public void addrealbetCaG(Label center,Label good,double num)
添加中心与轨道上物体的关系
public void addrealbetGaG(Label good1,Label good2,double num)添加轨道和轨道上的物体的关系
double getObjectDistributionEntropy(P3.CircularOrbit c)
int getLogicalDistance(P3.CircularOrbit c, SocialObject e1, SocialObject e2)
double getPhysicalDistance (P3.CircularOrbit c, SocialObject e1, SocialObject e2)
P3.Difference getDifference (SocialObject c1, SocialObject c2)
Test:
3.11 应对应用面临的新变化
3.11.1 TrackGame
3.11.2 StellarSystem
将画图函数改成椭圆就可以实现
3.11.3 AtomStructure
在CenterAtomObject类中有以上这几个内部类,并且写好了构造器,可以随时添加。
3.11.4 PersonalAppEcosystem
3.11.5 SocialNetworkCircle
添加关系的方向性:添加使用了MAP类型,这样构造有一个很明显的指向性,并且在读入边的时候,如果存在轨道物体向中心点的边则不操作,然后将其他所有的边加入,这里当然也包括了外层轨道到内层轨道的边。可以完成要求所要做的功能。
3.12 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚312change分支和master分支所指向的位置。
LAB1-------------------LAB2-----
LAB3-----
4 实验进度记录
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 |
时间段 |
计划任务 |
实际完成情况 |
4.15 |
18:00-23:00 |
写星球项目 |
未完成,开了个头 |
4.22 |
下午 |
写完星球项目 |
写完了星球项目 |
4.23-4.29 |
17:30-22:30 |
完成电子项目 |
完成了 |
4.29-5.4 |
17:00-22:00 |
完成人际关系项目 |
完成 |
5 实验过程中遇到的困难与解决途径
遇到的难点 |
解决途径 |
不会正则表达式
|
通过网上查找的信息以及从书上获得的信息完成了正则表达式 |
不会Java的图形化界面
|
通过一些视频和资料来自学完成 |
对项目的理解不够深彻
|
多读了几遍项目要求 |
6 实验过程中收获的经验、教训、感想
6.1 实验过程中收获的经验和教训
6.2 针对以下方面的感受
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使用,你是否体会到复用的好处?
(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后的编程中坚持这么做?
(3) 之前你将别人提供的API用于自己的程序开发中,本次实验你尝试着开发给别人使用的API,是否能够体会到其中的难处和乐趣?
(4) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
(6) Lab1和Lab2的大部分工作都不是从0开始,而是基于他人给出的设计方案和初始代码。本次实验是你完全从0开始进行ADT的设计并用OOP实现,经过三周之后,你感觉“设计ADT”的难度主要体现在哪些地方?你是如何克服的?
(7) 你在完成本实验时,是否有参考Lab4和Lab5的实验手册?若有,你如何在本次实验中同时去考虑后续两个实验的要求的?
(8) 关于本实验的工作量、难度、deadline。
(9) 到目前为止你对《软件构造》课程的评价。
在这次项目中我感受到了Java项目之间的深切的联系,对于ADT的应用我也有了新的体会。这次项目感觉上来说是比较难的。
对于ADT我的理解是:对于一个ADT来说,最重要的属性就是保有自己的不变量,不变量有一个最重要的属性就是:对于每种运行状态,不变量永远都是正确的。比如说对于一个不可变对象,那么他就是一个不变量。
ADT对于整个整个程序设计的过程中有着很重要的作用。使用ADT省略和隐藏了低级的细节,对系统的不同部分进行了很好的封装。ADT的内部实现也不会影响外部的抽象类型,抽象和内部类型是完全独立的
ADT是计算机科学中具有类似行为的特定类别的数据结构的数学模型;或者具有类似语义的一种或多种程序设计语言的数据类型。抽象数据类型是间接定义的,通过其上的可执行的操作以及这些操作的效果的数学约束(与可能的代价)。