目录
1 实验目标概述··· 1
2 实验环境配置··· 1
3 实验过程··· 1
3.1 待开发的三个应用场景··· 1
3.2 基于语法的图数据输入··· 2
3.3 面向复用的设计:CircularOrbit<L,E>· 2
3.4 public void readFile(String pathname);面向复用的设计:Track· 4
3.5 面向复用的设计:L· 5
3.6 面向复用的设计:PhysicalObject· 5
3.7 可复用API设计··· 6
3.8 图的可视化:第三方API的复用··· 6
3.9 设计模式应用··· 6
3.10 应用设计与开发··· 6
3.10.1 TrackGame·· 6
3.10.2 AtomStructure·· 7
3.10.3 SocialNetworkCircle·· 8
3.11 应对应用面临的新变化··· 9
3.12 Git仓库结构··· 9
4 实验进度记录··· 9
5 实验过程中遇到的困难与解决途径··· 10
6 实验过程中收获的经验、教训、感想··· 10
6.1 实验过程中收获的经验和教训··· 10
6.2 针对以下方面的感受··· 10
1 实验目标概述
2 实验环境配置
在这里给出你的GitHub Lab3仓库的URL地址(Lab3-学号)。
https://github.com/ComputerScienceHIT/Lab3-1170400307
3 实验过程
请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1 待开发的三个应用场景
首先请列出你要完成的具体应用场景(至少3个,1和2中选一,3必选,4和5中选一,鼓励完成更多的应用场景)。
l TrackGame
l AtomStructure
l SocialNetworkCircle
分析你所选定的多个应用场景的异同,理解需求:它们在哪些方面有共性、哪些方面有差异。
共性:
1)轨道都为圆形,其中包括轨道、中心物体、轨道物体。
2)都需要完成的功能有:添加/删除轨道,在某一轨道上添加/删除物体,获得轨道系统的熵值,获得逻辑距离,比较两个同类型轨道系统的差异,检查轨道系统是否合法,可视化。
差异:
1)TrackGame:需要编排。
2)AtomStructure:轨道物体都是值相同的对象,需要实现物体跃迁。
3)SocialNetworkCircle中需要实现物体关系及对应操作,需要计算信息扩散度。
3.2 基于语法的图数据输入
以下分别是三个应用的在输入处理中设计的正则表达式:
(1)String gameP = "Game\\s*::=\\s*([100|200|400,\\|]+)";
String athletePattern = "Athlete\\s*::=\\s*<([a-zA-Z]+),(\\d+),([A-Z]{3}),(\\d+),(\\d{1,2}\\.\\d{2}+)>";
String trackp = "NumOfTracks\\s*::=\\s*([4-9,10]+)";
(2)String elementNamePattern = "ElementName\\s*::=\\s*([A-Z]{1}[a-z]{0,1})";
String trackPattern = "NumberOfTracks\\s*::=\\s*(\\d+)";
String electronPatternString = "NumberOfElectron\\s*::=\\s*([\\d+\\/\\d+,;]+)";
(3)Pattern pattern1 = Pattern.compile("([A-Z]|[a-z]|[0-9])+");
Pattern pattern3 = Pattern.compile("[,][ ]*(([0][.][0-9]{0,2}[0-9])|([1]([.][0]{0,3})?))");
Pattern pattern2 = Pattern.compile("([0][.][0-9]{0,2}[1-9])|([1]([.][0]{0,3})?)");
3.3 面向复用的设计:CircularOrbit<L,E>
/**
* 增加一条轨道
*/
public boolean addtrack(track t);
/**
* 删除一条轨道
*/
public boolean removetrack(track t);
/**
* 设定中心点物体
*/
public void setcentralobject(L o);
/**
* 获取中心天体
*/
public L getcentralobject();
/**
* 增加物体到特定轨道
*/
public boolean addobjecttotrack(track t, E o);
/**
* 移除物体从特定轨道
*/
boolean removeobjecttotrack(track t, E o);
/**
* 移动物体到特定轨道
*/
public boolean transit(E o, track t);
/**
* 在物体之间添加关系
*/
public boolean addtrackrelation(E o1, E o2, double distance);
/**
* 在物体之间添加关系
*/
public boolean removetrackrelation(E object1, E object2, double distance);
/**
* 在中心点与轨道物体上添加关系
*/
public boolean addcentralrelation(L center, E object, double distance);
/**
* 计算熵值
*/
public double getentropy();
/**
* 获取已排序轨道表
*/
public List<track> getsortedtracks();
/**
* 获取轨道数量
*/
public Integer gettracknum();
/**
* 获取轨道t上的物体数
*/
public Integer getobjectnumontrack(track t);
/**
* 轨道t上的物体
*/
public List<E> getobjectontrack(track t);
/**
* 可视化
*/
public void drawpicture(String orbitname);
/**
* 从外部文件读取数据构造轨道系统对象
*/
3.4 面向复用的设计:Track
轨道类:唯一域为半径
double radius;
/*重写比较方法*/
@Override
public int compareTo(track that)
@Override
public int hashCode()
@Override
public boolean equals(Object obj)
3.5 面向复用的设计:L
构造了centralobject作为父类。
/**
* @return 半径
*/
public double getradius();
/**
* @return 极角
*/
public double getangle();
/**
* @return 姓名
*/
public String getname();
/*比较函数*/
public boolean equals(Object o);
/*打印字符串*/
public String toString();
3.6 面向复用的设计:PhysicalObject
/**
*
* @return 半径
*/
public double getradius();
/**
*
* @return 极角
*/
public double getangle();
/**
*
* @return 姓名
*/
public String getname();
/*比较函数*/
public boolean equals(Object o);
/*打印字符串*/
public String toString();
public int hashCode();
3.7 可复用API设计
1.计算轨道系统熵值:在泛型中已经具体实现。
2.获取最短逻辑距离。在泛型中已经具体实现。
3.获取物理距离:在绘图相关类中实现。
4.计算两个多轨道系统之间的差异:
在ConcreteCircularOrbit中我们将两个对应的轨道物体集合添加到Difference对象中。下面声明Difference的类设计。
每一对比较的轨道,各自形成集合且只保留各自轨道上独有的轨道物体(去除交集,这里的比较使用equalsObject进行值比较),通过两个集合构造trackDifference对象,一个轨道系统的Difference由多个trackDifference构成。在trackDifference中提供toString方法将差异转化为字串,需要注意的是,如果两个集合都为空则说明两轨道上物体完全相同,这时候不输出“物体差异”。
3.8 图的可视化:第三方API的复用
本实验中使用Swing实现可视化功能。同时,在简单的轨道系统可视化基础上,添加了一部分简单控件用于优化交互体验。
3.9 设计模式应用
Track,PhysicalObject等对象使用静态工厂方法实现。
3.10 应用设计与开发
利用上述设计和实现的ADT,实现手册里要求的各项功能。
以下各小节,只需保留和完成你所选定的应用即可。
3.10.1 TrackGame
排序策略
public void pickingrade() {
int num=gettracknum();
racer[] all=new racer[num];
int i=0;
for(track temp:tracks) {
all[i]=(racer) getobjectontrack(temp).get(0);
i++;
}
for(i=0;i<num;i++) {
for(int j=i;j<num;j++) {
if(all[i].getgrade()>all[j].getgrade())
{
racer x=new racer(null, num, 0, 0, null);
x=all[i];
all[i]=all[j];
all[j]=x;
}
}
}
i=0;
for(track temp:tracks) {
racer x=(racer) getobjectontrack(temp).get(0);
racer y=all[i];
removeobjecttotrack(temp, x);
addobjecttotrack(temp, y);
i++;
}
}
3.10.2 AtomStructure
/**
*
* @param electronic
* @param track
* @return if the electronic is not in destination and the transit completed successfully
*/
public boolean transit(Electronic electronic, Track<Electronic> track) {
if (electronic.getTrackRadius() == track.getRadius()) {
return false;
}
if (deleteElectronic(electronic)) {
track.add(electronic);
electronic.setTrackRadius(track.getRadius());
return true;
} else {
System.out.println("将该物体从原轨道上删除失败!");
return false;
}
}
3.10.3 SocialNetworkCircle
/**
* functon4: get the distance of the centralUser and the friend
* @param friend1 one friend
* @param friend2 another friend
* @return the distance
*/
public int getDistance(Friend friend1, Friend friend2) {
// Used to determine whether to be accessed or not
Map<Friend, Boolean> visited = new HashMap<>();
// Used to record distance
Map<Friend, Integer> distance = new HashMap<>();
for (Friend temp : friendShip) {
// Mark all persons as not accessed
visited.put(temp, false);
}
visited.put(friend1, true);
// 先广要用队列来做
Queue<Friend> queue = new LinkedBlockingQueue<>();
// Person 1 enters the queue
queue.add(friend1);
distance.put(friend1, 0);
if (friend1.equals(friend2)) {
return 0;
}
while (!queue.isEmpty()) {//Cycle until the queue is empty
Friend head = queue.poll();//Get the head element and bring it out
Friend tempt = head.getFriendShip().peek();//Get the first person associated with it
int i = 0;
while (tempt != null) {// Cycle until no one has a direct relationship with head
if (!visited.get(tempt)) {//If tempt is not accessed
if (tempt.equals(friend2)) {// If you find friend
return distance.get(head) + 1;
} else {//if not
visited.put(tempt, true);
distance.put(tempt, distance.get(head) + 1);
queue.add(tempt);//Bring the current friend into the queue
}
}
if (++i < head.getFriendShip().size()) {//Keep looking for people who are related to them
tempt = head.getFriendShip().get(i);
} else {
break;
}
}
}
return -1;
}
3.11 应对应用面临的新变化
未完成
3.12 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚312change分支和master分支所指向的位置。
4 实验进度记录
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
日期 |
时间段 |
计划任务 |
实际完成情况 |
4/11 |
10:46-17:05 |
ConcreteCircularOrbit大体结构 |
完成 |
4/12 |
20:00-0:02 |
完成TrackGame |
完成 |
4/14 |
18:00-23:35 |
完成SocialNetworkCircle |
完成 |
4/21 |
18:00-23:35 |
完成AtomStructyre |
完成 |
5.5 |
18:00-23:35 |
312change |
未完成 |
5 实验过程中遇到的困难与解决途径
遇到的难点 |
解决途径 |
设计模式不会 |
没写 |
代码难度太大 |
没有test |
6 实验过程中收获的经验、教训、感想
6.1 实验过程中收获的经验和教训
6.2 针对以下方面的感受
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使用,你是否体会到复用的好处?
面向ADT编程可复用。
复用确实简单一点,但找共同也很麻烦。
(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后的编程中坚持这么做?
设计ADT的复杂是为了他人使用时候的省心。
如果只是给我自己写的ADT我显然不愿意这么干,太麻烦了。但是如果想要设计ADT给别人用,给公司用,那我是很乐意的!
(3) 之前你将别人提供的API用于自己的程序开发中,本次实验你尝试着开发给别人使用的API,是否能够体会到其中的难处和乐趣?
本实验中API感觉难度一般,具体应用很难。
(4) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
设计模式的使用最大的好处就是简化程序吧,以及可维护性增强了。
(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
不理解什么是语法驱动编程。
(6) Lab1和Lab2的大部分工作都不是从0开始,而是基于他人给出的设计方案和初始代码。本次实验是你完全从0开始进行ADT的设计并用OOP实现,经过三周之后,你感觉“设计ADT”的难度主要体现在哪些地方?你是如何克服的?
难在设计吧:高级类反复设计了好几次;具体功能调用函数反复写了好几次。
(7) 你在完成本实验时,是否有参考Lab4和Lab5的实验手册?若有,你如何在本次实验中同时去考虑后续两个实验的要求的?
没有
(8) 关于本实验的工作量、难度、deadline。
没有完成,希望从宽给分,绕我一命。
(9) 到目前为止你对《软件构造》课程的评价。
挺好的,能够大幅度提高自己的工程能力吧,比如设计模式就是程序员精髓。